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 2020/02/10 22:44:31 UTC

[allura] branch db/8349 created (now 3b041f3)

This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a change to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git.


      at 3b041f3  [#8349] get syntax tests running on py3

This branch includes the following new commits:

     new c39f8c2  Misc: check apache config file as part of docker build
     new f543c2b  misc: avoid filter=foo erroring
     new a306637  Misc: avoid errors when sort param doesn't have a direction part
     new 02657c5  Misc: avoid errors when invalid page param
     new 8fc58ab  Misc: small trac import unicode fix; unlikely to be completely functional yet
     new 57c3cf4  [#8349] python-modernize -n -w --no-diffs -f except .
     new 707965e  [#8349] python-modernize -n -w --no-diffs -f print .
     new 6cb68ca  [#8349] python-modernize -n -w --no-diffs -f import .
     new 0d24f7e  [#8349] python-modernize -n -w --no-diffs -f imports_six -f urllib_six .
     new 6276654  [#8349] further updates after urllib import changes
     new 264fb1a  [#8349] python-modernize -n -w --no-diffs -f dict_six .
     new ae1d87e  [#8349] python-modernize -n -w --no-diffs -f next .
     new 5dd4056  [#8349] missed next() conversions
     new fb73880  [#8349] python-modernize -n -w --no-diffs -f libmodernize.fixes.fix_open .
     new 5e9dbf4  [#8349] various adjustments for open() changes
     new 390dbf2  [#8349] remove leading 0 numbers that are not really octal
     new 215ee5f  [#8349] python-modernize -n -w --no-diffs -f numliterals .
     new 751b5dd  [#8349] python-modernize -n -w --no-diffs -f raise .
     new 0d44182  [#8349] python-modernize -n -w --no-diffs -f basestring .
     new 107b818  [#8349] python-modernize -n -w --no-diffs -f xrange_six .
     new cd6aea4  [#8349] python-modernize -n -w --no-diffs -f filter .
     new 0b42e8d  [#8349] python-modernize -n -w --no-diffs -f zip .
     new f57671b  [#8349] python-modernize -n -w --no-diffs -f map .
     new 8e38a3b  [#8349] clearer code
     new 158a472  [#8349] python-modernize -n -w --no-diffs -f idioms .
     new 83a94ab  [#8349] revert an idiom change that needs to be an exact type() check still
     new a50dd4e  [#8349] python-modernize -n -w --no-diffs -f tuple_params .
     new 423d003  [#8349] python-modernize -n -w --no-diffs -f metaclass .
     new e0d292f  [#8349] python-modernize -n -w --no-diffs -f input_six .
     new 78c4372  [#8349] python-modernize -n -w --no-diffs -f exec .
     new 01bfc18  [#8349] python-modernize -n -w --no-diffs -f itertools_six -f itertools_imports_six .
     new 2163e96  [#8349] python-modernize -n -w --no-diffs -f types .
     new db8d22e  [#8349] python-modernize -n -w --no-diffs -f execfile .
     new 487829a  [#8349] python-modernize -n -w --no-diffs -f file .
     new 4bac431  [#8349] io.open and 'rb' tweaks after 'file' fixer
     new f946c4d  [#8349] python-modernize -n -w --no-diffs -f renames .
     new f5ec377  [#8349] python-modernize -n -w --no-diffs -f reduce .
     new 7dabc2c  [#8349] python-modernize -n -w --no-diffs -f six_raise .
     new 1dd19cb  [#8349] python-modernize -n -w --no-diffs -f methodattrs .
     new bdcbb9b  [#8349] again: python-modernize -n -w --no-diffs -f import .
     new 3b041f3  [#8349] get syntax tests running on py3

The 41 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[allura] 24/41: [#8349] clearer code

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 8e38a3bc5ad117bba8ed7bd4c6bbb8d0b04ebaca
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 14:43:16 2020 -0500

    [#8349] clearer code
---
 Allura/allura/model/discuss.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Allura/allura/model/discuss.py b/Allura/allura/model/discuss.py
index 41d2c6d..3331dc7 100644
--- a/Allura/allura/model/discuss.py
+++ b/Allura/allura/model/discuss.py
@@ -625,7 +625,8 @@ class Post(Message, VersionedArtifact, ActivityObject, ReactableArtifact):
 
     def add_multiple_attachments(self, file_info):
         if isinstance(file_info, list):
-            list(map(self.add_attachment, file_info))
+            for fi in file_info:
+                self.add_attachment(fi)
         else:
             self.add_attachment(file_info)
 


[allura] 38/41: [#8349] python-modernize -n -w --no-diffs -f six_raise .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 7dabc2c13a19a703b6affc2db799a987a2dba2c1
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 17:02:12 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f six_raise .
---
 Allura/allura/tasks/event_tasks.py | 3 ++-
 Allura/allura/tasks/index_tasks.py | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/Allura/allura/tasks/event_tasks.py b/Allura/allura/tasks/event_tasks.py
index fe537cd..11e04ce 100644
--- a/Allura/allura/tasks/event_tasks.py
+++ b/Allura/allura/tasks/event_tasks.py
@@ -20,6 +20,7 @@ import sys
 
 from allura.lib.decorators import task, event_handler
 from allura.lib.exceptions import CompoundError
+import six
 
 
 @task
@@ -32,6 +33,6 @@ def event(event_type, *args, **kwargs):
             exceptions.append(sys.exc_info())
     if exceptions:
         if len(exceptions) == 1:
-            raise exceptions[0][0], exceptions[0][1], exceptions[0][2]
+            six.reraise(exceptions[0][0], exceptions[0][1], exceptions[0][2])
         else:
             raise CompoundError(*exceptions)
diff --git a/Allura/allura/tasks/index_tasks.py b/Allura/allura/tasks/index_tasks.py
index 07ce887..a20dcfc 100644
--- a/Allura/allura/tasks/index_tasks.py
+++ b/Allura/allura/tasks/index_tasks.py
@@ -28,6 +28,7 @@ from allura.lib import helpers as h
 from allura.lib.decorators import task
 from allura.lib.exceptions import CompoundError
 from allura.lib.solr import make_solr_from_config
+import six
 
 
 log = logging.getLogger(__name__)
@@ -112,7 +113,7 @@ def add_artifacts(ref_ids, update_solr=True, update_refs=True, solr_hosts=None):
         __get_solr(solr_hosts).add(solr_updates)
 
     if len(exceptions) == 1:
-        raise exceptions[0][0], exceptions[0][1], exceptions[0][2]
+        six.reraise(exceptions[0][0], exceptions[0][1], exceptions[0][2])
     if exceptions:
         raise CompoundError(*exceptions)
 


[allura] 13/41: [#8349] missed next() conversions

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 5dd40566aab806cce37ae954abecbdaddefce819
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 13:33:46 2020 -0500

    [#8349] missed next() conversions
---
 ForgeGit/forgegit/tests/model/test_repository.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ForgeGit/forgegit/tests/model/test_repository.py b/ForgeGit/forgegit/tests/model/test_repository.py
index 0b6fe5c..a89624f 100644
--- a/ForgeGit/forgegit/tests/model/test_repository.py
+++ b/ForgeGit/forgegit/tests/model/test_repository.py
@@ -458,7 +458,7 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
         multipart_msg = sendmail.call_args_list[0][0][6]
         text_msg = sendmail.call_args_list[1][0][6]
         text_body = text_msg.get_payload(decode=True).decode('utf-8')
-        html_body = email.iterators.typed_subpart_iterator(multipart_msg, 'text', 'html').next()\
+        html_body = next(email.iterators.typed_subpart_iterator(multipart_msg, 'text', 'html'))\
             .get_payload(decode=True).decode('utf-8')
 
         # no extra HTML in commit messages


[allura] 03/41: Misc: avoid errors when sort param doesn't have a direction part

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit a306637b6a410069c99af78b4baa0acb073be056
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 11:46:56 2020 -0500

    Misc: avoid errors when sort param doesn't have a direction part
---
 ForgeTracker/forgetracker/model/ticket.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index e33ec35..fd4a412 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -1212,7 +1212,7 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
         q = cls.query.find(
             dict(query, app_config_id=app_config._id, deleted=deleted))
         q = q.sort('ticket_num', pymongo.DESCENDING)
-        if sort:
+        if sort and ' ' in sort:
             field, direction = sort.split()
             if field.startswith('_'):
                 field = 'custom_fields.' + field
@@ -1321,7 +1321,7 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
         search_query - query in solr syntax
         """
         solr_sort = None
-        if sort:
+        if sort and ' ' in sort:
             from forgetracker.tracker_main import _mongo_col_to_solr_col
             sort_split = sort.split(' ')
             solr_col = _mongo_col_to_solr_col(sort_split[0])


[allura] 11/41: [#8349] python-modernize -n -w --no-diffs -f dict_six .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 264fb1a0a088881c2d0fccaf74f9c559eeb359c1
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 13:28:29 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f dict_six .
---
 Allura/allura/app.py                               |  5 ++--
 Allura/allura/command/base.py                      |  2 +-
 Allura/allura/command/create_trove_categories.py   |  3 +-
 Allura/allura/command/show_models.py               | 23 ++++++++--------
 Allura/allura/controllers/auth.py                  |  9 +++---
 Allura/allura/controllers/discuss.py               |  3 +-
 Allura/allura/controllers/project.py               |  2 +-
 Allura/allura/controllers/repository.py            |  3 +-
 Allura/allura/controllers/rest.py                  |  3 +-
 Allura/allura/controllers/site_admin.py            |  3 +-
 Allura/allura/controllers/trovecategories.py       |  5 ++--
 Allura/allura/ext/admin/admin_main.py              | 11 ++++----
 Allura/allura/lib/app_globals.py                   |  2 +-
 Allura/allura/lib/decorators.py                    |  2 +-
 Allura/allura/lib/helpers.py                       | 24 ++++++++--------
 Allura/allura/lib/import_api.py                    |  2 +-
 Allura/allura/lib/macro.py                         |  2 +-
 Allura/allura/lib/multifactor.py                   |  3 +-
 Allura/allura/lib/patches.py                       |  3 +-
 Allura/allura/lib/plugin.py                        |  4 +--
 Allura/allura/lib/search.py                        |  4 +--
 Allura/allura/lib/security.py                      | 10 +++----
 Allura/allura/lib/solr.py                          |  2 +-
 Allura/allura/lib/utils.py                         |  2 +-
 Allura/allura/lib/validators.py                    |  3 +-
 Allura/allura/lib/widgets/discuss.py               |  7 +++--
 Allura/allura/lib/widgets/form_fields.py           |  7 +++--
 Allura/allura/lib/widgets/forms.py                 |  5 ++--
 Allura/allura/lib/widgets/user_profile.py          |  2 +-
 Allura/allura/model/artifact.py                    |  3 +-
 Allura/allura/model/index.py                       |  5 ++--
 Allura/allura/model/notification.py                |  3 +-
 Allura/allura/model/project.py                     | 23 ++++++++--------
 Allura/allura/model/repo_refresh.py                |  9 +++---
 Allura/allura/model/repository.py                  | 20 +++++++-------
 Allura/allura/model/session.py                     |  3 +-
 Allura/allura/scripts/trac_export.py               |  2 +-
 Allura/allura/tests/functional/test_auth.py        |  5 ++--
 Allura/allura/tests/functional/test_rest.py        |  6 ++--
 Allura/allura/tests/functional/test_site_admin.py  |  3 +-
 Allura/allura/tests/model/test_auth.py             |  6 ++--
 Allura/allura/tests/model/test_notification.py     |  2 +-
 Allura/allura/tests/model/test_repo.py             |  2 +-
 Allura/allura/tests/test_helpers.py                |  4 +--
 .../allura/tests/unit/test_ldap_auth_provider.py   |  5 ++--
 Allura/allura/webhooks.py                          |  2 +-
 Allura/allura/websetup/bootstrap.py                |  3 +-
 AlluraTest/alluratest/controller.py                |  3 +-
 AlluraTest/alluratest/validation.py                |  6 ++--
 ForgeBlog/forgeblog/main.py                        |  2 +-
 ForgeBlog/forgeblog/model/blog.py                  |  3 +-
 ForgeDiscussion/forgediscussion/import_support.py  |  9 +++---
 ForgeSVN/forgesvn/tests/model/test_repository.py   |  3 +-
 ForgeTracker/forgetracker/import_support.py        |  9 +++---
 ForgeTracker/forgetracker/model/ticket.py          | 32 +++++++++++-----------
 ForgeTracker/forgetracker/search.py                |  3 +-
 .../forgetracker/tests/functional/test_root.py     | 11 ++++----
 ForgeTracker/forgetracker/tests/test_app.py        |  2 +-
 .../forgetracker/tests/unit/test_ticket_model.py   |  2 +-
 ForgeTracker/forgetracker/tracker_main.py          |  3 +-
 ForgeTracker/forgetracker/widgets/ticket_search.py |  3 +-
 .../forgeuserstats/controllers/userstats.py        |  2 +-
 ForgeWiki/forgewiki/model/wiki.py                  |  2 +-
 fuse/accessfs.py                                   |  3 +-
 scripts/perf/benchmark-scm.py                      |  4 +--
 scripts/project-import.py                          |  5 ++--
 scripts/teamforge-import.py                        |  4 +--
 scripts/trac_import.py                             |  3 +-
 68 files changed, 207 insertions(+), 169 deletions(-)

diff --git a/Allura/allura/app.py b/Allura/allura/app.py
index 26b21f3..62ebca6 100644
--- a/Allura/allura/app.py
+++ b/Allura/allura/app.py
@@ -49,6 +49,7 @@ from allura.lib.decorators import require_post, memoize
 from allura.lib.utils import permanent_redirect, ConfigProxy
 from allura import model as M
 from allura.tasks import index_tasks
+import six
 
 log = logging.getLogger(__name__)
 
@@ -614,7 +615,7 @@ class Application(object):
         :return: a list of :class:`WebhookSender <allura.webhooks.WebhookSender>`
         """
         tool_name = self.config.tool_name.lower()
-        webhooks = [w for w in g.entry_points['webhooks'].itervalues()
+        webhooks = [w for w in six.itervalues(g.entry_points['webhooks'])
                     if tool_name in w.triggered_by]
         return webhooks
 
@@ -666,7 +667,7 @@ class Application(object):
     def admin_menu_delete_button(self):
         """Returns button for deleting an app if app can be deleted"""
         anchored_tools = self.project.neighborhood.get_anchored_tools()
-        anchored = self.tool_label.lower() in anchored_tools.keys()
+        anchored = self.tool_label.lower() in list(anchored_tools.keys())
         if self.uninstallable and not anchored:
             return SitemapEntry(
                 label='Delete Everything',
diff --git a/Allura/allura/command/base.py b/Allura/allura/command/base.py
index f7fd693..ac4c798 100644
--- a/Allura/allura/command/base.py
+++ b/Allura/allura/command/base.py
@@ -112,7 +112,7 @@ class Command(command.Command):
             # Probably being called from another script (websetup, perhaps?)
             log = logging.getLogger('allura.command')
             conf = tg.config
-        self.tools = tg.app_globals.entry_points['tool'].values()
+        self.tools = list(tg.app_globals.entry_points['tool'].values())
         for ep in h.iter_entry_points('allura.command_init'):
             log.info('Running command_init for %s', ep.name)
             ep.load()(conf)
diff --git a/Allura/allura/command/create_trove_categories.py b/Allura/allura/command/create_trove_categories.py
index aa3bb99..bf9ddc2 100644
--- a/Allura/allura/command/create_trove_categories.py
+++ b/Allura/allura/command/create_trove_categories.py
@@ -27,6 +27,7 @@ from mock import patch, Mock
 from . import base
 
 from allura import model as M
+import six
 
 log = logging.getLogger(__name__)
 
@@ -64,7 +65,7 @@ class CreateTroveCategoriesCommand(base.Command):
             sys.exit("Couldn't find TroveCategory with trove_cat_id=%s" %
                      trove_cat_id)
         for t in ts:
-            for k, v in attr_dict.iteritems():
+            for k, v in six.iteritems(attr_dict):
                 setattr(t, k, v)
 
     # patching to avoid a *lot* of event hooks firing, and taking a long long time
diff --git a/Allura/allura/command/show_models.py b/Allura/allura/command/show_models.py
index 50c5114..f38851d 100644
--- a/Allura/allura/command/show_models.py
+++ b/Allura/allura/command/show_models.py
@@ -35,6 +35,7 @@ from allura.lib.exceptions import CompoundError
 from allura.lib import helpers as h
 from allura.lib import utils
 from . import base
+import six
 
 
 class ShowModelsCommand(base.Command):
@@ -237,14 +238,14 @@ class EnsureIndexCommand(base.Command):
                 idx = project_indexes[cname]
             idx.extend(mgr.indexes)
         base.log.info('Updating indexes for main DB')
-        for odm_session, db_indexes in main_indexes.iteritems():
+        for odm_session, db_indexes in six.iteritems(main_indexes):
             db = odm_session.impl.db
-            for name, indexes in db_indexes.iteritems():
+            for name, indexes in six.iteritems(db_indexes):
                 self._update_indexes(db[name], indexes)
         base.log.info('Updating indexes for project DB')
         db = M.project_doc_session.db
         base.log.info('... DB: %s', db)
-        for name, indexes in project_indexes.iteritems():
+        for name, indexes in six.iteritems(project_indexes):
             self._update_indexes(db[name], indexes)
         base.log.info('Done updating indexes')
 
@@ -263,7 +264,7 @@ class EnsureIndexCommand(base.Command):
         unique_flag_drop = {}
         unique_flag_add = {}
         try:
-            existing_indexes = collection.index_information().iteritems()
+            existing_indexes = six.iteritems(collection.index_information())
         except OperationFailure:
             # exception is raised if db or collection doesn't exist yet
             existing_indexes = {}
@@ -282,13 +283,13 @@ class EnsureIndexCommand(base.Command):
                 else:
                     prev_indexes[iname] = keys
 
-        for iname, keys in unique_flag_drop.iteritems():
+        for iname, keys in six.iteritems(unique_flag_drop):
             self._recreate_index(collection, iname, list(keys), unique=False)
-        for iname, keys in unique_flag_add.iteritems():
+        for iname, keys in six.iteritems(unique_flag_add):
             self._recreate_index(collection, iname, list(keys), unique=True)
 
         # Ensure all indexes
-        for keys, idx in uindexes.iteritems():
+        for keys, idx in six.iteritems(uindexes):
             base.log.info('...... ensure %s:%s', collection.name, idx)
             while True:
                 try:
@@ -303,11 +304,11 @@ class EnsureIndexCommand(base.Command):
                 except DuplicateKeyError as err:
                     base.log.info('Found dupe key(%s), eliminating dupes', err)
                     self._remove_dupes(collection, idx.index_spec)
-        for keys, idx in indexes.iteritems():
+        for keys, idx in six.iteritems(indexes):
             base.log.info('...... ensure %s:%s', collection.name, idx)
             collection.ensure_index(idx.index_spec, background=True, **idx.index_options)
         # Drop obsolete indexes
-        for iname, keys in prev_indexes.iteritems():
+        for iname, keys in six.iteritems(prev_indexes):
             if keys not in indexes:
                 if self.options.clean:
                     base.log.info('...... drop index %s:%s', collection.name, iname)
@@ -315,7 +316,7 @@ class EnsureIndexCommand(base.Command):
                 else:
                     base.log.info('...... potentially unneeded index, could be removed by running with --clean %s:%s',
                                   collection.name, iname)
-        for iname, keys in prev_uindexes.iteritems():
+        for iname, keys in six.iteritems(prev_uindexes):
             if keys not in uindexes:
                 if self.options.clean:
                     base.log.info('...... drop index %s:%s', collection.name, iname)
@@ -359,7 +360,7 @@ class EnsureIndexCommand(base.Command):
 
 def build_model_inheritance_graph():
     graph = dict((m.mapped_class, ([], [])) for m in Mapper.all_mappers())
-    for cls, (parents, children) in graph.iteritems():
+    for cls, (parents, children) in six.iteritems(graph):
         for b in cls.__bases__:
             if b not in graph:
                 continue
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 3ec037e..44f17d7 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -57,6 +57,7 @@ from allura.lib.multifactor import TotpService, RecoveryCodeService
 from allura.lib import utils
 from allura.controllers import BaseController
 from allura.tasks.mail_tasks import send_system_mail_to_user
+import six
 
 log = logging.getLogger(__name__)
 
@@ -649,7 +650,7 @@ class PreferencesController(BaseController):
             c.user.set_pref('display_name', preferences['display_name'])
             if old != preferences['display_name']:
                 h.auditlog_user('Display Name changed %s => %s', old, preferences['display_name'])
-            for k, v in preferences.iteritems():
+            for k, v in six.iteritems(preferences):
                 if k == 'results_per_page':
                     v = int(v)
                 c.user.set_pref(k, v)
@@ -1165,14 +1166,14 @@ class SubscriptionsController(BaseController):
 
         # Dictionary containing all tools (subscribed and un-subscribed).
         my_tools = M.AppConfig.query.find(dict(
-            project_id={'$in': my_projects.keys()}))
+            project_id={'$in': list(my_projects.keys())}))
 
         # Dictionary containing all the currently subscribed tools for a given user.
         my_tools_subscriptions = dict(
             (mb.app_config_id, mb) for mb in M.Mailbox.query.find(dict(
                 user_id=c.user._id,
-                project_id={'$in': projects.keys()},
-                app_config_id={'$in': app_index.keys()},
+                project_id={'$in': list(projects.keys())},
+                app_config_id={'$in': list(app_index.keys())},
                 artifact_index_id=None)))
 
         # Add the remaining tools that are eligible for subscription.
diff --git a/Allura/allura/controllers/discuss.py b/Allura/allura/controllers/discuss.py
index f918538..f2ac57b 100644
--- a/Allura/allura/controllers/discuss.py
+++ b/Allura/allura/controllers/discuss.py
@@ -48,6 +48,7 @@ from allura.lib.widgets import form_fields as ffw
 from allura.model.auth import User
 from .attachments import AttachmentsController, AttachmentController
 from .feed import FeedArgs, FeedController
+import six
 
 log = logging.getLogger(__name__)
 
@@ -319,7 +320,7 @@ class PostController(BaseController):
             post_fields = self.W.edit_post.to_python(kw, None)  # could raise Invalid, but doesn't seem like it ever does
             file_info = post_fields.pop('file_info', None)
             self.post.add_multiple_attachments(file_info)
-            for k, v in post_fields.iteritems():
+            for k, v in six.iteritems(post_fields):
                 try:
                     setattr(self.post, k, v)
                 except AttributeError:
diff --git a/Allura/allura/controllers/project.py b/Allura/allura/controllers/project.py
index 44cf619..d061315 100644
--- a/Allura/allura/controllers/project.py
+++ b/Allura/allura/controllers/project.py
@@ -242,7 +242,7 @@ class NeighborhoodController(object):
             anchored_tools = neighborhood.get_anchored_tools()
             install_params = []
             for i, tool in enumerate(tools):
-                if (tool.lower() not in anchored_tools.keys()) and (c.project.app_instance(tool) is None):
+                if (tool.lower() not in list(anchored_tools.keys())) and (c.project.app_instance(tool) is None):
                     install_params.append(dict(ep_name=tool, ordinal=i + offset))
             c.project.install_apps(install_params)
         redirect(c.project.script_name + 'admin/?first-visit')
diff --git a/Allura/allura/controllers/repository.py b/Allura/allura/controllers/repository.py
index 3c9d191..1465b12 100644
--- a/Allura/allura/controllers/repository.py
+++ b/Allura/allura/controllers/repository.py
@@ -58,6 +58,7 @@ from allura.controllers.base import DispatchIndex
 from allura.controllers.rest import AppRestControllerMixin
 from allura.controllers.feed import FeedController, FeedArgs
 from .base import BaseController
+import six
 
 log = logging.getLogger(__name__)
 
@@ -270,7 +271,7 @@ class RepoRootController(BaseController, FeedController):
         parents = {}
         children = defaultdict(list)
         dates = {}
-        for row, (oid, ci) in enumerate(commits_by_id.iteritems()):
+        for row, (oid, ci) in enumerate(six.iteritems(commits_by_id)):
             parents[oid] = list(ci.parent_ids)
             dates[oid] = ci.committed.date
             for p_oid in ci.parent_ids:
diff --git a/Allura/allura/controllers/rest.py b/Allura/allura/controllers/rest.py
index 7977432..f488595 100644
--- a/Allura/allura/controllers/rest.py
+++ b/Allura/allura/controllers/rest.py
@@ -40,6 +40,7 @@ from allura.lib import plugin
 from allura.lib.exceptions import Invalid
 from allura.lib.decorators import require_post
 from allura.lib.security import has_access
+import six
 
 log = logging.getLogger(__name__)
 
@@ -84,7 +85,7 @@ class RestController(object):
         """
         summary = dict()
         stats = dict()
-        for stat, provider in g.entry_points['site_stats'].iteritems():
+        for stat, provider in six.iteritems(g.entry_points['site_stats']):
             stats[stat] = provider()
         if stats:
             summary['site_stats'] = stats
diff --git a/Allura/allura/controllers/site_admin.py b/Allura/allura/controllers/site_admin.py
index 96399b9..75922a4 100644
--- a/Allura/allura/controllers/site_admin.py
+++ b/Allura/allura/controllers/site_admin.py
@@ -51,6 +51,7 @@ import allura
 
 from six.moves.urllib.parse import urlparse
 from webhelpers import paginate
+import six
 
 
 log = logging.getLogger(__name__)
@@ -286,7 +287,7 @@ class SiteAdminController(object):
         def convert_fields(obj):
             # throw the type away (e.g. '_s' from 'url_s')
             result = {}
-            for k,val in obj.iteritems():
+            for k,val in six.iteritems(obj):
                 name = k.rsplit('_', 1)
                 if len(name) == 2:
                     name = name[0]
diff --git a/Allura/allura/controllers/trovecategories.py b/Allura/allura/controllers/trovecategories.py
index d793147..e52bcdb 100644
--- a/Allura/allura/controllers/trovecategories.py
+++ b/Allura/allura/controllers/trovecategories.py
@@ -33,6 +33,7 @@ from allura.lib.security import require_authenticated, require_site_admin
 from allura.lib.widgets import forms
 from allura.lib.plugin import SiteAdminExtension
 from allura.app import SitemapEntry
+import six
 
 
 class F(object):
@@ -100,7 +101,7 @@ class TroveCategoryController(BaseController):
             (self.generate_category(child) for child in category.subcategories)
         }
 
-        return category.fullname, OrderedDict(sorted(children.iteritems()))
+        return category.fullname, OrderedDict(sorted(six.iteritems(children)))
 
     @without_trailing_slash
     @expose('jinja:allura:templates/browse_trove_categories.html')
@@ -111,7 +112,7 @@ class TroveCategoryController(BaseController):
             for (key, value) in
             (self.generate_category(child) for child in parent_categories)
         }
-        return dict(tree=OrderedDict(sorted(tree.iteritems())))
+        return dict(tree=OrderedDict(sorted(six.iteritems(tree))))
 
     @classmethod
     def _create(cls, name, upper_id, shortname):
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index 631c415..a9fedc4 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -53,6 +53,7 @@ from allura.tasks import export_tasks
 from allura.lib.widgets.project_list import ProjectScreenshots
 
 from . import widgets as aw
+import six
 
 
 log = logging.getLogger(__name__)
@@ -103,7 +104,7 @@ class AdminApp(Application):
     @staticmethod
     def installable_tools_for(project):
         tools = []
-        for name, App in g.entry_points['tool'].iteritems():
+        for name, App in six.iteritems(g.entry_points['tool']):
             cfg = M.AppConfig(project_id=project._id, tool_name=name)
             app = App(project, cfg)
             if app.installable:
@@ -249,7 +250,7 @@ class ProjectAdminController(BaseController):
         first_troves = aslist(config.get('trovecategories.admin.order', 'topic,license,os'), ',')
         base_troves = [
             base_troves_by_name.pop(t) for t in first_troves
-        ] + sorted(base_troves_by_name.values(), key=attrgetter('fullname'))
+        ] + sorted(list(base_troves_by_name.values()), key=attrgetter('fullname'))
 
         trove_recommendations = {}
         for trove in base_troves:
@@ -613,7 +614,7 @@ class ProjectAdminController(BaseController):
                 App = g.entry_points['tool'][ep_name]
                 # pass only options which app expects
                 config_on_install = {
-                    k: v for (k, v) in kw.iteritems()
+                    k: v for (k, v) in six.iteritems(kw)
                     if k in [o.name for o in App.options_on_install()]
                 }
                 new_app = c.project.install_app(
@@ -705,7 +706,7 @@ class ProjectAdminRestController(BaseController):
         if not kw:
             raise exc.HTTPBadRequest('Expected kw params in the form of "ordinal: mount_point"')
         try:
-            sorted_tools = sorted(kw.items(), key=lambda x: int(x[0]))
+            sorted_tools = sorted(list(kw.items()), key=lambda x: int(x[0]))
         except ValueError:
             raise exc.HTTPBadRequest('Invalid kw: expected "ordinal: mount_point"')
 
@@ -1004,7 +1005,7 @@ class PermissionsController(BaseController):
             role_ids = map(ObjectId, group_ids + new_group_ids)
             permissions[perm] = role_ids
         c.project.acl = []
-        for perm, role_ids in permissions.iteritems():
+        for perm, role_ids in six.iteritems(permissions):
             role_names = lambda ids: ','.join(sorted(
                 pr.name for pr in M.ProjectRole.query.find(dict(_id={'$in': ids}))))
             old_role_ids = old_permissions.get(perm, [])
diff --git a/Allura/allura/lib/app_globals.py b/Allura/allura/lib/app_globals.py
index f809a60..577c261 100644
--- a/Allura/allura/lib/app_globals.py
+++ b/Allura/allura/lib/app_globals.py
@@ -299,7 +299,7 @@ class Globals(object):
 
         # Set listeners to update stats
         statslisteners = []
-        for name, ep in self.entry_points['stats'].iteritems():
+        for name, ep in six.iteritems(self.entry_points['stats']):
             statslisteners.append(ep())
         self.statsUpdater = PostEvent(statslisteners)
 
diff --git a/Allura/allura/lib/decorators.py b/Allura/allura/lib/decorators.py
index 3ce0f18..6a33304 100644
--- a/Allura/allura/lib/decorators.py
+++ b/Allura/allura/lib/decorators.py
@@ -161,7 +161,7 @@ def memoize(func, instance, args, kwargs):
         # decorating a method
         dic = getattr_(instance, "_memoize_dic__{}".format(func.__name__), dict)
 
-    cache_key = (args, frozenset(kwargs.items()))
+    cache_key = (args, frozenset(list(kwargs.items())))
     if cache_key in dic:
         return dic[cache_key]
     else:
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index 3812707..3f0b950 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -280,7 +280,7 @@ def push_config(obj, **kw):
 
     saved_attrs = {}
     new_attrs = []
-    for k, v in kw.iteritems():
+    for k, v in six.iteritems(kw):
         try:
             saved_attrs[k] = getattr(obj, k)
         except AttributeError:
@@ -289,7 +289,7 @@ def push_config(obj, **kw):
     try:
         yield obj
     finally:
-        for k, v in saved_attrs.iteritems():
+        for k, v in six.iteritems(saved_attrs):
             setattr(obj, k, v)
         for k in new_attrs:
             delattr(obj, k)
@@ -390,7 +390,7 @@ def encode_keys(d):
     a valid kwargs argument'''
     return dict(
         (k.encode('utf-8'), v)
-        for k, v in d.iteritems())
+        for k, v in six.iteritems(d))
 
 
 def vardec(fun):
@@ -422,7 +422,7 @@ def convert_bools(conf, prefix=''):
 
     return {
         k: (convert_value(v) if k.startswith(prefix) else v)
-        for k, v in conf.iteritems()
+        for k, v in six.iteritems(conf)
     }
 
 
@@ -547,7 +547,7 @@ def gen_message_id(_id=None):
 class ProxiedAttrMeta(type):
 
     def __init__(cls, name, bases, dct):
-        for v in dct.itervalues():
+        for v in six.itervalues(dct):
             if isinstance(v, attrproxy):
                 v.cls = cls
 
@@ -611,7 +611,7 @@ class fixed_attrs_proxy(proxy):
     """
     def __init__(self, obj, **kw):
         self._obj = obj
-        for k, v in kw.iteritems():
+        for k, v in six.iteritems(kw):
             setattr(self, k, v)
 
 
@@ -619,7 +619,7 @@ class fixed_attrs_proxy(proxy):
 def json_validation_error(controller, **kwargs):
     exc = request.validation['exception']
     result = dict(status='Validation Error',
-                  errors={fld: str(err) for fld, err in exc.error_dict.iteritems()},
+                  errors={fld: str(err) for fld, err in six.iteritems(exc.error_dict)},
                   value=exc.value,
                   params=kwargs)
     response.status = 400
@@ -647,7 +647,7 @@ def config_with_prefix(d, prefix):
     with the prefix stripped
     '''
     plen = len(prefix)
-    return dict((k[plen:], v) for k, v in d.iteritems()
+    return dict((k[plen:], v) for k, v in six.iteritems(d)
                 if k.startswith(prefix))
 
 
@@ -908,7 +908,7 @@ def ming_config(**conf):
         yield
     finally:
         Session._datastores = datastores
-        for name, session in Session._registry.iteritems():
+        for name, session in six.iteritems(Session._registry):
             session.bind = datastores.get(name, None)
             session._name = name
 
@@ -1071,7 +1071,7 @@ def iter_entry_points(group, *a, **kw):
         by_name = defaultdict(list)
         for ep in entry_points:
             by_name[ep.name].append(ep)
-        for name, eps in by_name.iteritems():
+        for name, eps in six.iteritems(by_name):
             ep_count = len(eps)
             if ep_count == 1:
                 yield eps[0]
@@ -1080,8 +1080,8 @@ def iter_entry_points(group, *a, **kw):
 
     def subclass(entry_points):
         loaded = dict((ep, ep.load()) for ep in entry_points)
-        for ep, cls in loaded.iteritems():
-            others = loaded.values()[:]
+        for ep, cls in six.iteritems(loaded):
+            others = list(loaded.values())[:]
             others.remove(cls)
             if all([issubclass(cls, other) for other in others]):
                 return ep
diff --git a/Allura/allura/lib/import_api.py b/Allura/allura/lib/import_api.py
index 7a8a6bd..257f8c8 100644
--- a/Allura/allura/lib/import_api.py
+++ b/Allura/allura/lib/import_api.py
@@ -46,7 +46,7 @@ class AlluraImportApiClient(object):
         if self.verbose:
             log.info("Import API URL: %s", url)
 
-        params = self.sign(six.moves.urllib.parse.urlparse(url).path, params.items())
+        params = self.sign(six.moves.urllib.parse.urlparse(url).path, list(params.items()))
 
         while True:
             try:
diff --git a/Allura/allura/lib/macro.py b/Allura/allura/lib/macro.py
index c8dc885..e348bad 100644
--- a/Allura/allura/lib/macro.py
+++ b/Allura/allura/lib/macro.py
@@ -407,7 +407,7 @@ def include(ref=None, repo=None, **kw):
 
 @macro()
 def img(src=None, **kw):
-    attrs = ('%s="%s"' % t for t in kw.iteritems())
+    attrs = ('%s="%s"' % t for t in six.iteritems(kw))
     included = request.environ.setdefault('allura.macro.att_embedded', set())
     included.add(src)
     if '://' in src:
diff --git a/Allura/allura/lib/multifactor.py b/Allura/allura/lib/multifactor.py
index c21b197..b756930 100644
--- a/Allura/allura/lib/multifactor.py
+++ b/Allura/allura/lib/multifactor.py
@@ -41,6 +41,7 @@ from ming.odm import session
 
 from allura.model.multifactor import RecoveryCode
 from allura.lib.utils import umask
+import six
 
 
 log = logging.getLogger(__name__)
@@ -230,7 +231,7 @@ class GoogleAuthenticatorFile(object):
     def dump(self):
         lines = []
         lines.append(b32encode(self.key).replace('=', ''))
-        for opt, value in self.options.iteritems():
+        for opt, value in six.iteritems(self.options):
             parts = ['"', opt]
             if value is not None:
                 parts.append(value)
diff --git a/Allura/allura/lib/patches.py b/Allura/allura/lib/patches.py
index c419954..743c2f2 100644
--- a/Allura/allura/lib/patches.py
+++ b/Allura/allura/lib/patches.py
@@ -27,6 +27,7 @@ import mock
 import json
 
 from allura.lib import helpers as h
+import six
 
 _patched = False
 def apply():
@@ -60,7 +61,7 @@ def apply():
         else:
             return
 
-        for content_type, content_engine in engines.iteritems():
+        for content_type, content_engine in six.iteritems(engines):
             template = template.split(':', 1)
             template.extend(content_engine[2:])
             try:
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index 4f80a58..e090e71 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -1063,7 +1063,7 @@ class ProjectRegistrationProvider(object):
             for i, tool in enumerate(project_template['tools'].keys()):
                 tool_config = project_template['tools'][tool]
                 tool_options = tool_config.get('options', {})
-                for k, v in tool_options.iteritems():
+                for k, v in six.iteritems(tool_options):
                     if isinstance(v, basestring):
                         tool_options[k] = \
                             string.Template(v).safe_substitute(
@@ -1532,7 +1532,7 @@ class ThemeProvider(object):
 
         if note_to_show:
             cookie_chunks = []
-            for note_id, views_closed in cookie_info.iteritems():
+            for note_id, views_closed in six.iteritems(cookie_info):
                 cookie_chunks.append('{}-{}-{}'.format(note_id, views_closed[0], views_closed[1]))
             set_cookie_value = '_'.join(sorted(cookie_chunks))
             return note_to_show, set_cookie_value
diff --git a/Allura/allura/lib/search.py b/Allura/allura/lib/search.py
index ac45ee4..6b86179 100644
--- a/Allura/allura/lib/search.py
+++ b/Allura/allura/lib/search.py
@@ -115,7 +115,7 @@ class SearchIndexable(object):
         # the same suffixes, but different field types. E.g.:
         # query 'shortname:test' with fields.keys() == ['name_t', 'shortname_s']
         # will be translated to 'shortname_t:test', which makes no sense
-        fields = sorted(fields.keys(), key=len, reverse=True)
+        fields = sorted(list(fields.keys()), key=len, reverse=True)
         for f in fields:
             if '_' in f:
                 base, typ = f.rsplit('_', 1)
@@ -171,7 +171,7 @@ def search_artifact(atype, q, history=False, rows=10, short_timeout=False, filte
         fq.append('project_id_s:%s' % c.project._id)
 
     fq += kw.pop('fq', [])
-    for name, values in (filter or {}).iteritems():
+    for name, values in six.iteritems((filter or {})):
         field_name = name + '_s'
         parts = []
         for v in values:
diff --git a/Allura/allura/lib/security.py b/Allura/allura/lib/security.py
index 3497305..3969ea8 100644
--- a/Allura/allura/lib/security.py
+++ b/Allura/allura/lib/security.py
@@ -105,7 +105,7 @@ class Credentials(object):
         roles_by_project = dict((pid, []) for pid in project_ids)
         for role in q:
             roles_by_project[role['project_id']].append(role)
-        for pid, roles in roles_by_project.iteritems():
+        for pid, roles in six.iteritems(roles_by_project):
             self.users[user_id, pid] = RoleCache(self, roles)
 
     def load_project_roles(self, *project_ids):
@@ -120,7 +120,7 @@ class Credentials(object):
         roles_by_project = dict((pid, []) for pid in project_ids)
         for role in q:
             roles_by_project[role['project_id']].append(role)
-        for pid, roles in roles_by_project.iteritems():
+        for pid, roles in six.iteritems(roles_by_project):
             self.projects[pid] = RoleCache(self, roles)
 
     def project_roles(self, project_id):
@@ -179,7 +179,7 @@ class RoleCache(object):
         self.q = q
 
     def find(self, **kw):
-        tests = kw.items()
+        tests = list(kw.items())
 
         def _iter():
             for r in self:
@@ -200,7 +200,7 @@ class RoleCache(object):
         return None
 
     def __iter__(self):
-        return self.index.itervalues()
+        return six.itervalues(self.index)
 
     def __len__(self):
         return len(self.index)
@@ -252,7 +252,7 @@ class RoleCache(object):
     @LazyProperty
     def reaching_roles(self):
         def _iter():
-            to_visit = self.index.items()
+            to_visit = list(self.index.items())
             project_ids = set([r['project_id'] for _id, r in to_visit])
             pr_index = {r['_id']: r for r in self.cred.project_role.find({
                 'project_id': {'$in': list(project_ids)},
diff --git a/Allura/allura/lib/solr.py b/Allura/allura/lib/solr.py
index ab5390d..18c6bd3 100644
--- a/Allura/allura/lib/solr.py
+++ b/Allura/allura/lib/solr.py
@@ -53,7 +53,7 @@ def escape_solr_arg(term):
     """ Apply escaping to the passed in query terms
         escaping special characters like : , etc"""
     term = term.replace('\\', r'\\')   # escape \ first
-    for char, escaped_char in escape_rules.iteritems():
+    for char, escaped_char in six.iteritems(escape_rules):
         term = term.replace(char, escaped_char)
 
     return term
diff --git a/Allura/allura/lib/utils.py b/Allura/allura/lib/utils.py
index 8e42ae2..02b8bd0 100644
--- a/Allura/allura/lib/utils.py
+++ b/Allura/allura/lib/utils.py
@@ -810,7 +810,7 @@ def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
 
 
 def generate_smart_str(params):
-    for (key, value) in params.iteritems():
+    for (key, value) in six.iteritems(params):
         yield smart_str(key), smart_str(value)
 
 
diff --git a/Allura/allura/lib/validators.py b/Allura/allura/lib/validators.py
index ffc1a2a..9c8367b 100644
--- a/Allura/allura/lib/validators.py
+++ b/Allura/allura/lib/validators.py
@@ -25,6 +25,7 @@ from formencode import validators as fev
 from tg import tmpl_context as c
 from . import helpers as h
 from datetime import datetime
+import six
 
 
 class URL(fev.URL):
@@ -299,7 +300,7 @@ class UserMapJsonFile(JsonFile):
     def _to_python(self, value, state):
         value = super(self.__class__, self)._to_python(value, state)
         try:
-            for k, v in value.iteritems():
+            for k, v in six.iteritems(value):
                 if not(isinstance(k, basestring) and isinstance(v, basestring)):
                     raise
             return json.dumps(value) if self.as_string else value
diff --git a/Allura/allura/lib/widgets/discuss.py b/Allura/allura/lib/widgets/discuss.py
index 1979901..25919cd 100644
--- a/Allura/allura/lib/widgets/discuss.py
+++ b/Allura/allura/lib/widgets/discuss.py
@@ -30,6 +30,7 @@ from allura.lib import validators as V
 from allura.lib.widgets import form_fields as ffw
 from allura.lib.widgets import forms as ff
 from allura import model as M
+import six
 
 
 class NullValidator(fev.FancyValidator):
@@ -268,7 +269,7 @@ class HierWidget(ew_core.Widget):
         return response
 
     def resources(self):
-        for w in self.widgets.itervalues():
+        for w in six.itervalues(self.widgets):
             for r in w.resources():
                 yield r
 
@@ -315,7 +316,7 @@ class Post(HierWidget):
     def resources(self):
         for r in super(Post, self).resources():
             yield r
-        for w in self.widgets.itervalues():
+        for w in six.itervalues(self.widgets):
             for r in w.resources():
                 yield r
         yield ew.CSSScript('''
@@ -361,7 +362,7 @@ class Thread(HierWidget):
     def resources(self):
         for r in super(Thread, self).resources():
             yield r
-        for w in self.widgets.itervalues():
+        for w in six.itervalues(self.widgets):
             for r in w.resources():
                 yield r
         yield ew.JSScript('''
diff --git a/Allura/allura/lib/widgets/form_fields.py b/Allura/allura/lib/widgets/form_fields.py
index 0ee7067..52c678a 100644
--- a/Allura/allura/lib/widgets/form_fields.py
+++ b/Allura/allura/lib/widgets/form_fields.py
@@ -27,6 +27,7 @@ from webhelpers import paginate
 
 import ew as ew_core
 import ew.jinja2_ew as ew
+import six
 
 log = logging.getLogger(__name__)
 
@@ -328,7 +329,7 @@ class PageList(ew_core.Widget):
     @property
     def url_params(self, **kw):
         url_params = dict()
-        for k, v in request.params.iteritems():
+        for k, v in six.iteritems(request.params):
             if k not in ['limit', 'count', 'page']:
                 url_params[k] = v
         return url_params
@@ -346,7 +347,7 @@ class PageSize(ew_core.Widget):
     @property
     def url_params(self, **kw):
         url_params = dict()
-        for k, v in request.params.iteritems():
+        for k, v in six.iteritems(request.params):
             if k not in ['limit', 'count', 'page']:
                 url_params[k] = v
         return url_params
@@ -445,7 +446,7 @@ class StateField(JQueryMixin, ew.CompoundField):
 
     @property
     def fields(self):
-        return [self.selector] + self.states.values()
+        return [self.selector] + list(self.states.values())
 
 
 class DateField(JQueryMixin, ew.TextField):
diff --git a/Allura/allura/lib/widgets/forms.py b/Allura/allura/lib/widgets/forms.py
index 4b3e9e4..67baa1f 100644
--- a/Allura/allura/lib/widgets/forms.py
+++ b/Allura/allura/lib/widgets/forms.py
@@ -36,6 +36,7 @@ from allura.lib import plugin
 from allura.lib.widgets import form_fields as ffw
 from allura.lib import exceptions as forge_exc
 from allura import model as M
+import six
 
 
 log = logging.getLogger(__name__)
@@ -260,7 +261,7 @@ class PersonalDataForm(ForgeForm):
                 validator=V.MapValidator(country_names, not_empty=False),
                 options=[ew.Option(py_value=" ", label=" -- Unknown -- ", selected=False)] +
                         [ew.Option(py_value=c, label=n, selected=False)
-                         for c, n in sorted(country_names.items(),
+                         for c, n in sorted(list(country_names.items()),
                                             key=lambda (k, v): v)],
                 attrs={'onchange': 'selectTimezone(this.value)'}),
             ew.TextField(
@@ -978,7 +979,7 @@ class NeighborhoodAddProjectForm(ForgeForm):
     def fields(self):
         provider = plugin.ProjectRegistrationProvider.get()
         tools_options = []
-        for ep, tool in g.entry_points["tool"].iteritems():
+        for ep, tool in six.iteritems(g.entry_points["tool"]):
             if tool.status == 'production' and tool._installable(tool_name=ep,
                                                                  nbhd=c.project.neighborhood,
                                                                  project_tools=[]):
diff --git a/Allura/allura/lib/widgets/user_profile.py b/Allura/allura/lib/widgets/user_profile.py
index bc517fa..fd2e17e 100644
--- a/Allura/allura/lib/widgets/user_profile.py
+++ b/Allura/allura/lib/widgets/user_profile.py
@@ -76,7 +76,7 @@ class SectionsUtil(object):
         for section in re.split(r'\s*,\s*', section_ordering):
             if section in sections:
                 ordered_sections.append(sections.pop(section))
-        sections = ordered_sections + sections.values()
+        sections = ordered_sections + list(sections.values())
         return sections
 
 
diff --git a/Allura/allura/model/artifact.py b/Allura/allura/model/artifact.py
index 37425fa..d3a6f1c 100644
--- a/Allura/allura/model/artifact.py
+++ b/Allura/allura/model/artifact.py
@@ -47,6 +47,7 @@ from .project import AppConfig
 from .notification import MailFooter
 
 from .filesystem import File
+import six
 
 log = logging.getLogger(__name__)
 
@@ -632,7 +633,7 @@ class VersionedArtifact(Artifact):
     def revert(self, version):
         ss = self.get_version(version)
         old_version = self.version
-        for k, v in ss.data.iteritems():
+        for k, v in six.iteritems(ss.data):
             setattr(self, k, v)
         self.version = old_version
 
diff --git a/Allura/allura/model/index.py b/Allura/allura/model/index.py
index 47c6ddb..8cd1828 100644
--- a/Allura/allura/model/index.py
+++ b/Allura/allura/model/index.py
@@ -38,6 +38,7 @@ from allura.lib import helpers as h
 
 from .session import main_doc_session, main_orm_session
 from .project import Project
+import six
 
 log = logging.getLogger(__name__)
 
@@ -167,13 +168,13 @@ class Shortlink(object):
                 else:
                     result[link] = parsed_links.pop(link)
             q = cls.query.find(dict(
-                link={'$in': links_by_artifact.keys()},
+                link={'$in': list(links_by_artifact.keys())},
                 project_id={'$in': list(project_ids)}
             ), validate=False)
             matches_by_artifact = dict(
                 (link, list(matches))
                 for link, matches in groupby(q, key=lambda s: unquote(s.link)))
-            for link, d in parsed_links.iteritems():
+            for link, d in six.iteritems(parsed_links):
                 matches = matches_by_artifact.get(unquote(d['artifact']), [])
                 matches = (
                     m for m in matches
diff --git a/Allura/allura/model/notification.py b/Allura/allura/model/notification.py
index 4c41129..cc67922 100644
--- a/Allura/allura/model/notification.py
+++ b/Allura/allura/model/notification.py
@@ -58,6 +58,7 @@ import allura.tasks.mail_tasks
 
 from .session import main_orm_session
 from .auth import User, AlluraUserProperty
+import six
 
 
 log = logging.getLogger(__name__)
@@ -651,7 +652,7 @@ class Mailbox(MappedClass):
                         'Error sending notification: %s to mbox %s (user %s)',
                         n._id, self._id, self.user_id)
             # Accumulate messages from same address with same subject
-            for (subject, from_address, reply_to_address, author_id), ns in ngroups.iteritems():
+            for (subject, from_address, reply_to_address, author_id), ns in six.iteritems(ngroups):
                 try:
                     if len(ns) == 1:
                         ns[0].send_direct(self.user_id)
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index 97319e3..49b3dbe 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -62,6 +62,7 @@ from .types import ACL, ACE
 from .monq_model import MonQTask
 
 from .filesystem import File
+import six
 
 log = logging.getLogger(__name__)
 
@@ -480,7 +481,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
         project_index = dict((p._id, p) for p in projects)
         result = dict((p._id, None) for p in projects)
         for icon in ProjectFile.query.find(dict(
-                project_id={'$in': result.keys()},
+                project_id={'$in': list(result.keys())},
                 category='icon')):
             result[icon.project_id] = project_index[icon.project_id].url() + 'icon'
         return result
@@ -491,7 +492,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
         from .artifact import AwardGrant
         result = dict((p._id, []) for p in projects)
         for award in AwardGrant.query.find(dict(
-                granted_to_project_id={'$in': result.keys()})):
+                granted_to_project_id={'$in': list(result.keys())})):
             result[award.granted_to_project_id].append(award)
         return result
 
@@ -574,8 +575,8 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
                     entry.ui_icon = 'tool-%s' % entry.tool_name.lower()
                     if is_nofollow_url(entry.url):
                         entry.extra_html_attrs = {'rel': 'nofollow'}
-                    if not self.is_nbhd_project and (entry.tool_name.lower() in anchored_tools.keys()):
-                        ordinal = anchored_tools.keys().index(
+                    if not self.is_nbhd_project and (entry.tool_name.lower() in list(anchored_tools.keys())):
+                        ordinal = list(anchored_tools.keys()).index(
                             entry.tool_name.lower())
                     elif ac.tool_name == 'admin':
                         ordinal = 100
@@ -610,7 +611,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
         i = 0
         new_tools = []
         if not self.is_nbhd_project:
-            for tool, label in anchored_tools.iteritems():
+            for tool, label in six.iteritems(anchored_tools):
                 if (tool not in installed_tools) and (self.app_instance(tool) is None):
                     try:
                         new_tools.append(
@@ -633,7 +634,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
                          icon=s.ui_icon or 'tool-admin',
                          tool_name=s.tool_name or 'sub',
                          mount_point=s.mount_point,
-                         is_anchored=s.tool_name in anchored_tools.keys(),
+                         is_anchored=s.tool_name in list(anchored_tools.keys()),
                          )
             if admin_options and s.tool_name and s.mount_point:
                 try:
@@ -707,7 +708,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
                         e.mount_point = None
                         e.extra_html_attrs = {}
                         grouped_nav[tool_name].children.append(e)
-        return grouped_nav.values()
+        return list(grouped_nav.values())
 
     def parent_iter(self):
         yield self
@@ -762,7 +763,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
             mount_points[App] = mount_point
 
         # count mount point names
-        mount_point_counts = Counter(mount_points.values())
+        mount_point_counts = Counter(list(mount_points.values()))
 
         # install each app with unique names
         for app_params in apps_params:
@@ -824,7 +825,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
         options['mount_label'] = mount_label or App.default_mount_label or mount_point
         options['ordinal'] = int(ordinal)
         options_on_install = {o.name: o for o in App.options_on_install()}
-        for o, val in override_options.iteritems():
+        for o, val in six.iteritems(override_options):
             if o in options_on_install:
                 val = self._validate_tool_option(options_on_install[o], val)
             options[o] = val
@@ -895,8 +896,8 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
         for ac in self.app_configs:
             App = g.entry_points['tool'].get(ac.tool_name)
             if include_hidden or App and not App.hidden:
-                if not self.is_nbhd_project and (ac.tool_name.lower() in anchored_tools.keys()):
-                    ordinal = anchored_tools.keys().index(ac.tool_name.lower())
+                if not self.is_nbhd_project and (ac.tool_name.lower() in list(anchored_tools.keys())):
+                    ordinal = list(anchored_tools.keys()).index(ac.tool_name.lower())
                 else:
                     ordinal = int(ac.options.get('ordinal', 0)) + i
                 result.append({'ordinal': int(ordinal), 'ac': ac})
diff --git a/Allura/allura/model/repo_refresh.py b/Allura/allura/model/repo_refresh.py
index 49d911b..86edbd8 100644
--- a/Allura/allura/model/repo_refresh.py
+++ b/Allura/allura/model/repo_refresh.py
@@ -39,6 +39,7 @@ from allura.model.repository import Commit, Tree, LastCommit, ModelCache
 from allura.model.index import ArtifactReferenceDoc, ShortlinkDoc
 from allura.model.auth import User
 from allura.model.timeline import TransientActor
+import six
 
 log = logging.getLogger(__name__)
 
@@ -106,10 +107,10 @@ def refresh_repo(repo, all_commits=False, notify=True, new_clone=False, commits_
         from allura.webhooks import RepoPushWebhookSender
         by_branches, by_tags = _group_commits(repo, commit_ids)
         params = []
-        for b, commits in by_branches.iteritems():
+        for b, commits in six.iteritems(by_branches):
             ref = 'refs/heads/{}'.format(b) if b != '__default__' else None
             params.append(dict(commit_ids=commits, ref=ref))
-        for t, commits in by_tags.iteritems():
+        for t, commits in six.iteritems(by_tags):
             ref = 'refs/tags/{}'.format(t)
             params.append(dict(commit_ids=commits, ref=ref))
         if params:
@@ -306,11 +307,11 @@ def _group_commits(repo, commit_ids):
         if tags:
             current_tags = tags
         for b in current_branches:
-            if b not in by_branches.keys():
+            if b not in list(by_branches.keys()):
                 by_branches[b] = []
             by_branches[b].append(commit)
         for t in current_tags:
-            if t not in by_tags.keys():
+            if t not in list(by_tags.keys()):
                 by_tags[t] = []
             by_tags[t].append(commit)
     return by_branches, by_tags
diff --git a/Allura/allura/model/repository.py b/Allura/allura/model/repository.py
index ac80114..4a951d0 100644
--- a/Allura/allura/model/repository.py
+++ b/Allura/allura/model/repository.py
@@ -1062,7 +1062,7 @@ class Commit(RepoObject, ActivityObject):
     repo = None
 
     def __init__(self, **kw):
-        for k, v in kw.iteritems():
+        for k, v in six.iteritems(kw):
             setattr(self, k, v)
 
     @property
@@ -1626,13 +1626,13 @@ class LastCommit(RepoObject):
                 entries = {}
             # paths are fully-qualified; shorten them back to just node names
             entries = {
-                os.path.basename(path): commit_id for path, commit_id in entries.iteritems()}
+                os.path.basename(path): commit_id for path, commit_id in six.iteritems(entries)}
         # update with the nodes changed in this tree's commit
         entries.update({node: tree.commit._id for node in changed})
         # convert to a list of dicts, since mongo doesn't handle arbitrary keys
         # well (i.e., . and $ not allowed)
         entries = [{'name': name, 'commit_id': value}
-                   for name, value in entries.iteritems()]
+                   for name, value in six.iteritems(entries)]
         lcd = cls(
             commit_id=tree.commit._id,
             path=path,
@@ -1690,7 +1690,7 @@ class ModelCache(object):
     def _normalize_query(self, query):
         _query = query
         if not isinstance(_query, tuple):
-            _query = tuple(sorted(_query.items(), key=lambda k: k[0]))
+            _query = tuple(sorted(list(_query.items()), key=lambda k: k[0]))
         return _query
 
     def _model_query(self, cls):
@@ -1789,7 +1789,7 @@ class ModelCache(object):
             return len(self._instance_cache[cls])
 
     def instance_ids(self, cls):
-        return self._instance_cache[cls].keys()
+        return list(self._instance_cache[cls].keys())
 
     def batch_load(self, cls, query, attrs=None):
         '''
@@ -1800,7 +1800,7 @@ class ModelCache(object):
         the given query.
         '''
         if attrs is None:
-            attrs = query.keys()
+            attrs = list(query.keys())
         for result in self._model_query(cls).find(query):
             keys = {a: getattr(result, a) for a in attrs}
             self.set(cls, keys, result)
@@ -1864,9 +1864,9 @@ class GitLikeTree(object):
     def __repr__(self):
         # this can't change, is used in hex() above
         lines = ['t %s %s' % (t.hex(), h.really_unicode(name))
-                 for name, t in self.trees.iteritems()]
+                 for name, t in six.iteritems(self.trees)]
         lines += ['b %s %s' % (oid, h.really_unicode(name))
-                  for name, oid in self.blobs.iteritems()]
+                  for name, oid in six.iteritems(self.blobs)]
         return h.really_unicode('\n'.join(sorted(lines))).encode('utf-8')
 
     def __unicode__(self):
@@ -1877,9 +1877,9 @@ class GitLikeTree(object):
         lines = [' ' * indent + 't %s %s' %
                  (name, '\n' + t.unicode_full_tree(indent + 2, show_id=show_id)
                   if recurse else t.hex())
-                 for name, t in sorted(self.trees.iteritems())]
+                 for name, t in sorted(six.iteritems(self.trees))]
         lines += [' ' * indent + 'b %s %s' % (name, oid if show_id else '')
-                  for name, oid in sorted(self.blobs.iteritems())]
+                  for name, oid in sorted(six.iteritems(self.blobs))]
         output = h.really_unicode('\n'.join(lines)).encode('utf-8')
         return output
 
diff --git a/Allura/allura/model/session.py b/Allura/allura/model/session.py
index cb4255a..1b44c48 100644
--- a/Allura/allura/model/session.py
+++ b/Allura/allura/model/session.py
@@ -29,6 +29,7 @@ from contextlib import contextmanager
 
 from allura.lib.utils import chunked_list
 from allura.tasks import index_tasks
+import six
 
 log = logging.getLogger(__name__)
 
@@ -105,7 +106,7 @@ class IndexerSessionExtension(ManagedSessionExtension):
         for obj_list, action in actions:
             if obj_list:
                 types_objects_map = self._objects_by_types(obj_list)
-                for class_path, obj_list in types_objects_map.iteritems():
+                for class_path, obj_list in six.iteritems(types_objects_map):
                     tasks = self.TASKS.get(class_path)
                     if tasks:
                         self._index_action(tasks, obj_list, action)
diff --git a/Allura/allura/scripts/trac_export.py b/Allura/allura/scripts/trac_export.py
index bbdde95..ecadac5 100644
--- a/Allura/allura/scripts/trac_export.py
+++ b/Allura/allura/scripts/trac_export.py
@@ -105,7 +105,7 @@ class TracExport(object):
     def remap_fields(self, dict):
         "Remap fields to adhere to standard taxonomy."
         out = {}
-        for k, v in dict.iteritems():
+        for k, v in six.iteritems(dict):
             key = self.match_pattern(r'\W*(\w+)\W*', k)
             out[self.FIELD_MAP.get(key, key)] = v
 
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index def21d4..67479e1 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -54,6 +54,7 @@ from allura import model as M
 from allura.lib import plugin
 from allura.lib import helpers as h
 from allura.lib.multifactor import TotpService, RecoveryCodeService
+import six
 
 
 def unentity(s):
@@ -848,7 +849,7 @@ class TestAuth(TestController):
 
     def _find_subscriptions_form(self, r):
         form = None
-        for f in r.forms.itervalues():
+        for f in six.itervalues(r.forms):
             if f.action == 'update_subscriptions':
                 form = f
                 break
@@ -857,7 +858,7 @@ class TestAuth(TestController):
 
     def _find_subscriptions_field(self, form, subscribed=False):
         field_name = None
-        for k, v in form.fields.iteritems():
+        for k, v in six.iteritems(form.fields):
             if subscribed:
                 check = c and v[0].value == 'on'
             else:
diff --git a/Allura/allura/tests/functional/test_rest.py b/Allura/allura/tests/functional/test_rest.py
index 310d172..b885ed4 100644
--- a/Allura/allura/tests/functional/test_rest.py
+++ b/Allura/allura/tests/functional/test_rest.py
@@ -438,7 +438,7 @@ class TestDoap(TestRestApiBase):
         user = maintainers[0].find(self.foaf + 'Person')
         assert_equal(user.find(self.foaf + 'name').text, 'Test Admin')
         assert_equal(user.find(self.foaf + 'nick').text, 'test-admin')
-        assert_equal(user.find(self.foaf + 'homepage').items()[0][1],
+        assert_equal(list(user.find(self.foaf + 'homepage').items())[0][1],
                      'http://localhost/u/test-admin/')
 
     @td.with_tool('test', 'Tickets', 'bugs')
@@ -457,7 +457,7 @@ class TestDoap(TestRestApiBase):
         p = r.xml.find(self.ns + 'Project')
         tools = p.findall(self.ns_sf + 'feature')
         tools = [(t.find(self.ns_sf + 'Feature').find(self.ns + 'name').text,
-                  t.find(self.ns_sf + 'Feature').find(self.foaf + 'page').items()[0][1])
+                  list(t.find(self.ns_sf + 'Feature').find(self.foaf + 'page').items())[0][1])
                  for t in tools]
         assert_in(('Tickets', 'http://localhost/p/test/bugs/'), tools)
         assert_in(('Tickets', 'http://localhost/p/test/private-bugs/'), tools)
@@ -468,7 +468,7 @@ class TestDoap(TestRestApiBase):
         p = r.xml.find(self.ns + 'Project')
         tools = p.findall(self.ns_sf + 'feature')
         tools = [(t.find(self.ns_sf + 'Feature').find(self.ns + 'name').text,
-                  t.find(self.ns_sf + 'Feature').find(self.foaf + 'page').items()[0][1])
+                  list(t.find(self.ns_sf + 'Feature').find(self.foaf + 'page').items())[0][1])
                  for t in tools]
         assert_in(('Tickets', 'http://localhost/p/test/bugs/'), tools)
         assert_not_in(('Tickets', 'http://localhost/p/test/private-bugs/'), tools)
diff --git a/Allura/allura/tests/functional/test_site_admin.py b/Allura/allura/tests/functional/test_site_admin.py
index 93f30f2..f5ce746 100644
--- a/Allura/allura/tests/functional/test_site_admin.py
+++ b/Allura/allura/tests/functional/test_site_admin.py
@@ -35,6 +35,7 @@ from allura.tests import decorators as td
 from allura.lib import helpers as h
 from allura.lib.decorators import task
 from allura.lib.plugin import LocalAuthenticationProvider
+import six
 
 
 class TestSiteAdmin(TestController):
@@ -504,7 +505,7 @@ class TestUserDetails(TestController):
     def test_add_comment(self):
         r = self.app.get('/nf/admin/user/test-user')
         assert_not_in('Comment by test-admin: I was hêre!', r)
-        form = [f for f in r.forms.itervalues() if f.action.endswith('add_audit_trail_entry')][0]
+        form = [f for f in six.itervalues(r.forms) if f.action.endswith('add_audit_trail_entry')][0]
         assert_equal(form['username'].value, 'test-user')
         form['comment'] = 'I was hêre!'
         r = form.submit()
diff --git a/Allura/allura/tests/model/test_auth.py b/Allura/allura/tests/model/test_auth.py
index 79a7786..039a969 100644
--- a/Allura/allura/tests/model/test_auth.py
+++ b/Allura/allura/tests/model/test_auth.py
@@ -254,9 +254,9 @@ def test_default_project_roles():
         for pr in M.ProjectRole.query.find(dict(
             project_id=c.project._id)).all()
         if pr.name)
-    assert 'Admin' in roles.keys(), roles.keys()
-    assert 'Developer' in roles.keys(), roles.keys()
-    assert 'Member' in roles.keys(), roles.keys()
+    assert 'Admin' in list(roles.keys()), list(roles.keys())
+    assert 'Developer' in list(roles.keys()), list(roles.keys())
+    assert 'Member' in list(roles.keys()), list(roles.keys())
     assert roles['Developer']._id in roles['Admin'].roles
     assert roles['Member']._id in roles['Developer'].roles
 
diff --git a/Allura/allura/tests/model/test_notification.py b/Allura/allura/tests/model/test_notification.py
index ec2546a..31e2fe5 100644
--- a/Allura/allura/tests/model/test_notification.py
+++ b/Allura/allura/tests/model/test_notification.py
@@ -493,7 +493,7 @@ class TestSiteNotification(unittest.TestCase):
         assert isinstance(note_json, dict)
 
     def test_json_keys(self):
-        keys = self.note.__json__().keys()
+        keys = list(self.note.__json__().keys())
         assert 'active' in keys
         assert 'impressions' in keys
         assert 'content' in keys
diff --git a/Allura/allura/tests/model/test_repo.py b/Allura/allura/tests/model/test_repo.py
index 8eea5db..160f1ac 100644
--- a/Allura/allura/tests/model/test_repo.py
+++ b/Allura/allura/tests/model/test_repo.py
@@ -213,7 +213,7 @@ class TestLastCommit(unittest.TestCase):
         return commit
 
     def _log(self, revs, path, id_only=True, limit=None):
-        for commit_id, commit in reversed(self.repo._commits.items()):
+        for commit_id, commit in reversed(list(self.repo._commits.items())):
             if path in commit.changed_paths:
                 yield commit_id
 
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index 514f43e..bf1d5e0 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -186,7 +186,7 @@ def test_context_setters():
 
 def test_encode_keys():
     kw = h.encode_keys({'foo': 5})
-    assert type(kw.keys()[0]) != six.text_type
+    assert type(list(kw.keys())[0]) != six.text_type
 
 
 def test_ago():
@@ -229,7 +229,7 @@ def test_paging_sanitizer():
         (10, 0): (10, 0),
         ('junk', 'more junk'): (25, 0),
     }
-    for input, output in test_data.iteritems():
+    for input, output in six.iteritems(test_data):
         assert (h.paging_sanitizer(*input)) == output
 
 
diff --git a/Allura/allura/tests/unit/test_ldap_auth_provider.py b/Allura/allura/tests/unit/test_ldap_auth_provider.py
index 4ced1ab..5945581 100644
--- a/Allura/allura/tests/unit/test_ldap_auth_provider.py
+++ b/Allura/allura/tests/unit/test_ldap_auth_provider.py
@@ -35,6 +35,7 @@ from alluratest.controller import setup_basic_test
 from allura.lib import plugin
 from allura.lib import helpers as h
 from allura import model as M
+import six
 
 
 class TestLdapAuthenticationProvider(object):
@@ -77,7 +78,7 @@ class TestLdapAuthenticationProvider(object):
             'password': 'test-password',
         }
         self.provider.request.method = 'POST'
-        self.provider.request.body = '&'.join(['%s=%s' % (k,v) for k,v in params.iteritems()]).encode('utf-8')
+        self.provider.request.body = '&'.join(['%s=%s' % (k,v) for k,v in six.iteritems(params)]).encode('utf-8')
         ldap.dn.escape_dn_chars = lambda x: x
 
         self.provider._login()
@@ -96,7 +97,7 @@ class TestLdapAuthenticationProvider(object):
             'password': 'test-password',
         }
         self.provider.request.method = 'POST'
-        self.provider.request.body = '&'.join(['%s=%s' % (k,v) for k,v in params.iteritems()]).encode('utf-8')
+        self.provider.request.body = '&'.join(['%s=%s' % (k,v) for k,v in six.iteritems(params)]).encode('utf-8')
         ldap.dn.escape_dn_chars = lambda x: x
         dn = 'uid=%s,ou=people,dc=localdomain' % params['username']
         conn = ldap.initialize.return_value
diff --git a/Allura/allura/webhooks.py b/Allura/allura/webhooks.py
index 4c8447f..31b6bef 100644
--- a/Allura/allura/webhooks.py
+++ b/Allura/allura/webhooks.py
@@ -221,7 +221,7 @@ class WebhookRestController(BaseController):
         error = getattr(e, 'error_dict', None)
         if error:
             _error = {}
-            for k, v in error.iteritems():
+            for k, v in six.iteritems(error):
                 _error[k] = six.text_type(v)
             return _error
         error = getattr(e, 'msg', None)
diff --git a/Allura/allura/websetup/bootstrap.py b/Allura/allura/websetup/bootstrap.py
index fc5b703..7ddc24f 100644
--- a/Allura/allura/websetup/bootstrap.py
+++ b/Allura/allura/websetup/bootstrap.py
@@ -44,6 +44,7 @@ from allura.command import CreateTroveCategoriesCommand
 from allura.websetup.schema import REGISTRY
 
 from forgewiki import model as WM
+import six
 
 log = logging.getLogger(__name__)
 
@@ -254,7 +255,7 @@ def bootstrap(command, conf, vars):
             log.info('Registering initial apps')
             with h.push_config(c, user=u_admin):
                 p0.install_apps([{'ep_name': ep_name}
-                                 for ep_name, app in g.entry_points['tool'].iteritems()
+                                 for ep_name, app in six.iteritems(g.entry_points['tool'])
                                  if app._installable(tool_name=ep_name,
                                                      nbhd=n_projects,
                                                      project_tools=[])
diff --git a/AlluraTest/alluratest/controller.py b/AlluraTest/alluratest/controller.py
index b1c48b4..b5e53de 100644
--- a/AlluraTest/alluratest/controller.py
+++ b/AlluraTest/alluratest/controller.py
@@ -46,6 +46,7 @@ from allura.lib import helpers as h
 from allura.websetup.schema import REGISTRY
 #from allura.lib.custom_middleware import environ as ENV, MagicalC
 from .validation import ValidatingTestApp
+import six
 
 DFL_APP_NAME = 'main'
 
@@ -212,7 +213,7 @@ class TestController(object):
 
     def find_form(self, resp, cond):
         """Find form on the page that meets given condition"""
-        for f in resp.forms.itervalues():
+        for f in six.itervalues(resp.forms):
             if cond(f):
                 return f
 
diff --git a/AlluraTest/alluratest/validation.py b/AlluraTest/alluratest/validation.py
index 8e94b14..df2f246 100644
--- a/AlluraTest/alluratest/validation.py
+++ b/AlluraTest/alluratest/validation.py
@@ -226,7 +226,7 @@ class AntiSpamTestApp(TestApp):
                 antispam.enc('honey0'): '',
                 antispam.enc('honey1'): '',
             }
-            for k, v in kwargs['params'].iteritems():
+            for k, v in six.iteritems(kwargs['params']):
                 params[antispam.enc(k)] = v
             params['_session_id'] = kwargs['params'].get('_session_id')  # exclude csrf token from encryption
             kwargs['params'] = params
@@ -240,7 +240,7 @@ class AntiSpamTestApp(TestApp):
         timestamp = form['timestamp'].value
         spinner = form['spinner'].value
         antispam = utils.AntiSpam(timestamp=int(timestamp), spinner=utils.AntiSpam._unwrap(spinner))
-        names = form.fields.keys()
+        names = list(form.fields.keys())
         name_mapping = {}
         for name in names:
             try:
@@ -258,7 +258,7 @@ class PostParamCheckingTestApp(AntiSpamTestApp):
             return
         # params can be a list or a dict
         if hasattr(params, 'items'):
-            params = params.items()
+            params = list(params.items())
         for k, v in params:
             if not isinstance(k, basestring):
                 raise TypeError('%s key %s is %s, not str' %
diff --git a/ForgeBlog/forgeblog/main.py b/ForgeBlog/forgeblog/main.py
index 56488b5..89d7ebd 100644
--- a/ForgeBlog/forgeblog/main.py
+++ b/ForgeBlog/forgeblog/main.py
@@ -435,7 +435,7 @@ class PostController(BaseController, FeedController):
         old_text = self.post.text
         if attachment is not None:
             self.post.add_multiple_attachments(attachment)
-        for k, v in kw.iteritems():
+        for k, v in six.iteritems(kw):
             setattr(self.post, k, v)
         self.post.commit()
         notification_tasks.send_usermentions_notification.post(self.post.index_id(), kw['text'], old_text)
diff --git a/ForgeBlog/forgeblog/model/blog.py b/ForgeBlog/forgeblog/model/blog.py
index 2583ba9..d2b56bb 100644
--- a/ForgeBlog/forgeblog/model/blog.py
+++ b/ForgeBlog/forgeblog/model/blog.py
@@ -36,6 +36,7 @@ from allura.model.timeline import ActivityObject
 from allura.model.types import MarkdownCache
 from allura.lib import helpers as h
 from allura.lib import utils
+import six
 
 config = utils.ConfigProxy(
     common_suffix='forgemail.domain')
@@ -295,7 +296,7 @@ class BlogPost(M.VersionedArtifact, ActivityObject):
     def new(cls, **kw):
         post = cls()
         subscribe = kw.pop('subscribe', False)
-        for k, v in kw.iteritems():
+        for k, v in six.iteritems(kw):
             setattr(post, k, v)
         post.neighborhood_id = c.project.neighborhood_id
         post.make_slug()
diff --git a/ForgeDiscussion/forgediscussion/import_support.py b/ForgeDiscussion/forgediscussion/import_support.py
index f1040f6..cd8a334 100644
--- a/ForgeDiscussion/forgediscussion/import_support.py
+++ b/ForgeDiscussion/forgediscussion/import_support.py
@@ -29,6 +29,7 @@ from tg import tmpl_context as c
 from allura import model as M
 
 from forgediscussion import model as DM
+import six
 
 log = logging.getLogger(__name__)
 
@@ -52,11 +53,11 @@ def perform_import(json, username_mapping, default_username=None, create_users=F
                     c.app.config.options.mount_point,
                     w)
 
-    for name, forum in json.forums.iteritems():
+    for name, forum in six.iteritems(json.forums):
         log.info('... %s has %d threads with %d total posts',
-                 name, len(forum.threads), sum(len(t) for t in forum.threads.itervalues()))
+                 name, len(forum.threads), sum(len(t) for t in six.itervalues(forum.threads)))
 
-    for name, forum in json.forums.iteritems():
+    for name, forum in six.iteritems(json.forums):
         log.info('... creating %s/%s: %s',
                  c.project.shortname,
                  c.app.config.options.mount_point,
@@ -66,7 +67,7 @@ def perform_import(json, username_mapping, default_username=None, create_users=F
             name=forum['name'],
             shortname=forum['name'],
             description=forum['description'])
-        for tid, posts in forum.threads.iteritems():
+        for tid, posts in six.iteritems(forum.threads):
             rest, head = posts[:-1], posts[-1]
             t = DM.ForumThread.new(
                 _id=tid,
diff --git a/ForgeSVN/forgesvn/tests/model/test_repository.py b/ForgeSVN/forgesvn/tests/model/test_repository.py
index f00ecc1..8f18ad4 100644
--- a/ForgeSVN/forgesvn/tests/model/test_repository.py
+++ b/ForgeSVN/forgesvn/tests/model/test_repository.py
@@ -50,6 +50,7 @@ from forgesvn import model as SM
 from forgesvn.model.svn import svn_path_exists
 from forgesvn.tests import with_svn
 from allura.tests.decorators import with_tool
+import six
 
 
 class TestNewRepo(unittest.TestCase):
@@ -652,7 +653,7 @@ class _Test(unittest.TestCase):
         t, isnew = M.repository.Tree.upsert(object_id)
         repo = getattr(self, 'repo', None)
         t.repo = repo
-        for k, v in kwargs.iteritems():
+        for k, v in six.iteritems(kwargs):
             if isinstance(v, basestring):
                 obj = M.repository.Blob(
                     t, k, self.idgen.next())
diff --git a/ForgeTracker/forgetracker/import_support.py b/ForgeTracker/forgetracker/import_support.py
index 6b3faaf..0fb4103 100644
--- a/ForgeTracker/forgetracker/import_support.py
+++ b/ForgeTracker/forgetracker/import_support.py
@@ -34,6 +34,7 @@ from allura.lib.plugin import ImportIdConverter
 
 # Local imports
 from forgetracker import model as TM
+import six
 
 try:
     from forgeimporters.base import ProjectExtractor
@@ -199,7 +200,7 @@ class ImportSupport(object):
 
     def make_artifact(self, ticket_dict):
         remapped = {}
-        for f, v in ticket_dict.iteritems():
+        for f, v in six.iteritems(ticket_dict):
             transform = self.FIELD_MAP.get(f, ())
             if transform is None:
                 continue
@@ -309,7 +310,7 @@ class ImportSupport(object):
     def validate_user_mapping(self):
         if 'user_map' not in self.options:
             self.options['user_map'] = {}
-        for foreign_user, allura_user in self.options['user_map'].iteritems():
+        for foreign_user, allura_user in six.iteritems(self.options['user_map']):
             u = M.User.by_username(allura_user)
             if not u:
                 raise ImportException(
@@ -325,7 +326,7 @@ class ImportSupport(object):
         self.validate_user_mapping()
 
         project_doc = json.loads(doc)
-        tracker_names = project_doc['trackers'].keys()
+        tracker_names = list(project_doc['trackers'].keys())
         if len(tracker_names) > 1:
             self.errors.append('Only single tracker import is supported')
             return self.errors, self.warnings
@@ -345,7 +346,7 @@ option user_map to avoid losing username information. Unknown users: %s''' % unk
         self.validate_user_mapping()
 
         project_doc = json.loads(doc)
-        tracker_names = project_doc['trackers'].keys()
+        tracker_names = list(project_doc['trackers'].keys())
         if len(tracker_names) > 1:
             self.errors.append('Only single tracker import is supported')
             return self.errors, self.warnings
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index d10de45..17e890e 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -282,7 +282,7 @@ class Globals(MappedClass):
             app_config_id=self.app_config_id)).sort('ticket_num').all()
         filtered = self.filtered_by_subscription({t._id: t for t in tickets})
         original_ticket_nums = {t._id: t.ticket_num for t in tickets}
-        users = User.query.find({'_id': {'$in': filtered.keys()}}).all()
+        users = User.query.find({'_id': {'$in': list(filtered.keys())}}).all()
         moved_tickets = {}
         for ticket in tickets:
             moved = ticket.move(tracker, notify=False)
@@ -324,7 +324,7 @@ class Globals(MappedClass):
                 'original_num': original_ticket_nums[_id],
                 'destination_num': moved_tickets[_id].ticket_num,
                 'summary': moved_tickets[_id].summary
-            } for _id, t in moved_tickets.iteritems()
+            } for _id, t in six.iteritems(moved_tickets)
                 if (not t.private or
                     self.app_config.options.get('TicketMonitoringType') ==
                     'AllTicketChanges')]
@@ -392,7 +392,7 @@ class Globals(MappedClass):
             if labels:
                 values['labels'] = self.append_new_labels(
                     ticket.labels, labels.split(','))
-            for k, v in sorted(values.iteritems()):
+            for k, v in sorted(six.iteritems(values)):
                 if k == 'deleted':
                     if v:
                         ticket.soft_delete()
@@ -422,7 +422,7 @@ class Globals(MappedClass):
                         v,
                         getattr(ticket, k))
                 setattr(ticket, k, v)
-            for k, v in sorted(custom_values.iteritems()):
+            for k, v in sorted(six.iteritems(custom_values)):
                 def cf_val(cf):
                     return ticket.get_custom_user(cf.name) \
                         if cf.type == 'user' \
@@ -445,7 +445,7 @@ class Globals(MappedClass):
 
         filtered_changes = self.filtered_by_subscription(changed_tickets)
         users = User.query.find(
-            {'_id': {'$in': filtered_changes.keys()}}).all()
+            {'_id': {'$in': list(filtered_changes.keys())}}).all()
 
         def changes_iter(user):
             for t_id in filtered_changes.get(user._id, []):
@@ -463,12 +463,12 @@ class Globals(MappedClass):
         )
         tmpl = g.jinja2_env.get_template('forgetracker:data/mass_report.html')
         head = []
-        for f, v in sorted(values.iteritems()):
+        for f, v in sorted(six.iteritems(values)):
             if f == 'assigned_to_id':
                 user = User.query.get(_id=v)
                 v = user.display_name if user else v
             head.append('- **%s**: %s' % (get_label(f), v))
-        for f, v in sorted(custom_values.iteritems()):
+        for f, v in sorted(six.iteritems(custom_values)):
             cf = custom_fields[f]
             if cf.type == 'user':
                 user = User.by_username(v)
@@ -515,19 +515,19 @@ class Globals(MappedClass):
     def filtered_by_subscription(self, tickets, project_id=None, app_config_id=None):
         p_id = project_id if project_id else c.project._id
         ac_id = app_config_id if app_config_id else self.app_config_id
-        ticket_ids = tickets.keys()
+        ticket_ids = list(tickets.keys())
         tickets_index_id = {
-            ticket.index_id(): t_id for t_id, ticket in tickets.iteritems()}
+            ticket.index_id(): t_id for t_id, ticket in six.iteritems(tickets)}
         subscriptions = Mailbox.query.find({
             'project_id': p_id,
             'app_config_id': ac_id,
-            'artifact_index_id': {'$in': tickets_index_id.keys() + [None]}})
+            'artifact_index_id': {'$in': list(tickets_index_id.keys()) + [None]}})
         filtered = {}
         for subscription in subscriptions:
             if subscription.artifact_index_id is None:
                 # subscribed to entire tool, will see all changes
                 filtered[subscription.user_id] = set(ticket_ids)
-            elif subscription.artifact_index_id in tickets_index_id.keys():
+            elif subscription.artifact_index_id in list(tickets_index_id.keys()):
                 user = filtered.setdefault(subscription.user_id, set())
                 user.add(tickets_index_id[subscription.artifact_index_id])
         return filtered
@@ -578,7 +578,7 @@ class TicketHistory(Snapshot):
         # `text`, so we're appending all other field values into `text`, to match on it too.
         result['text'] += '\n'.join([six.text_type(v)
                                      for k, v
-                                     in result.iteritems()
+                                     in six.iteritems(result)
                                      if k not in ('id', 'project_id_s')
                                      ])
         return result
@@ -714,7 +714,7 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
             votes_total_i=(self.votes_up - self.votes_down),
             import_id_s=ImportIdConverter.get().simplify(self.import_id)
         )
-        for k, v in self.custom_fields.iteritems():
+        for k, v in six.iteritems(self.custom_fields):
             # Pre solr-4.2.1 code expects all custom fields to be indexed
             # as strings.
             if not config.get_bool('new_solr'):
@@ -734,7 +734,7 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
         # match on it too.
         result['text'] += '\n'.join([six.text_type(v)
                                      for k, v
-                                     in result.iteritems()
+                                     in six.iteritems(result)
                                      if k not in ('id', 'project_id_s')
                                      ])
         return result
@@ -987,7 +987,7 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
             if 'custom_fields' not in ticket_form:
                 ticket_form['custom_fields'] = dict()
             ticket_form['custom_fields']['_milestone'] = milestone
-        for k, v in ticket_form.iteritems():
+        for k, v in six.iteritems(ticket_form):
             if k == 'assigned_to':
                 if v:
                     user = c.project.user_in_project(v)
@@ -999,7 +999,7 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
             else:
                 setattr(self, k, v)
         if 'custom_fields' in ticket_form:
-            for k, v in ticket_form['custom_fields'].iteritems():
+            for k, v in six.iteritems(ticket_form['custom_fields']):
                 if k in custom_users:
                     # restrict custom user field values to project members
                     user = self.app_config.project.user_in_project(v)
diff --git a/ForgeTracker/forgetracker/search.py b/ForgeTracker/forgetracker/search.py
index c4dbe1c..ca15e85 100644
--- a/ForgeTracker/forgetracker/search.py
+++ b/ForgeTracker/forgetracker/search.py
@@ -19,6 +19,7 @@ from __future__ import absolute_import
 from tg import tmpl_context as c
 
 from allura.lib.search import search
+import six
 
 
 FACET_PARAMS = {
@@ -58,7 +59,7 @@ def get_facets(solr_hit):
     """
     result = {}
     if solr_hit is not None:
-        for facet_name, values in solr_hit.facets['facet_fields'].iteritems():
+        for facet_name, values in six.iteritems(solr_hit.facets['facet_fields']):
             field_name = facet_name.rsplit('_s', 1)[0]
             values = [(values[i], values[i+1]) for i in xrange(0, len(values), 2)]
             result[field_name] = values
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index 7d5b710..fe74abc 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -58,6 +58,7 @@ from allura.lib.utils import urlencode
 from allura.tests import decorators as td
 from allura.tasks import mail_tasks
 from ming.orm.ormsession import ThreadLocalORMSession
+import six
 
 
 class TrackerTestController(TestController):
@@ -84,7 +85,7 @@ class TrackerTestController(TestController):
         response = self.app.get(mount_point + 'new/',
                                 extra_environ=extra_environ)
         form = self._find_new_ticket_form(response)
-        for k, v in kw.iteritems():
+        for k, v in six.iteritems(kw):
             if type(v) == bool:
                 form['ticket_form.%s' % k] = v
             else:
@@ -1952,7 +1953,7 @@ class TestFunctionalController(TrackerTestController):
             tickets[1]._id: tickets[1],
         }
         filtered_changes = c.app.globals.filtered_by_subscription(changes)
-        filtered_users = [uid for uid, data in filtered_changes.iteritems()]
+        filtered_users = [uid for uid, data in six.iteritems(filtered_changes)]
         assert_equal(sorted(filtered_users),
                      sorted([u._id for u in users[:-1] + [admin]]))
         ticket_ids = [t._id for t in tickets]
@@ -2298,7 +2299,7 @@ class TestFunctionalController(TrackerTestController):
         r = self.app.get('/p/test/bugs/2/')
         field_name = None  # comment text textarea name
         form = r.forms['ticket-form']
-        for name, field in form.fields.iteritems():
+        for name, field in six.iteritems(form.fields):
             if field[0].tag == 'textarea':
                 field_name = name
         assert field_name, "Can't find comment field"
@@ -2405,7 +2406,7 @@ class TestFunctionalController(TrackerTestController):
         r = self.app.get('/p/test/bugs/1/')
         field_name = None  # comment text textarea name
         form = r.forms['ticket-form']
-        for name, field in form.fields.iteritems():
+        for name, field in six.iteritems(form.fields):
             if field[0].tag == 'textarea':
                 field_name = name
         assert field_name, "Can't find comment field"
@@ -2619,7 +2620,7 @@ class TestMilestoneAdmin(TrackerTestController):
                  show_in_search='on',
                  type='milestone',
                  milestones=[
-                     dict((k, v) for k, v in d.iteritems()) for d in mf['milestones']])
+                     dict((k, v) for k, v in six.iteritems(d)) for d in mf['milestones']])
             for mf in milestones]}
         return self._post(params)
 
diff --git a/ForgeTracker/forgetracker/tests/test_app.py b/ForgeTracker/forgetracker/tests/test_app.py
index d902a8d..f1cfd2f 100644
--- a/ForgeTracker/forgetracker/tests/test_app.py
+++ b/ForgeTracker/forgetracker/tests/test_app.py
@@ -127,7 +127,7 @@ class TestBulkExport(TrackerTestController):
         assert_equal(posts_foo[0]['text'], 'silly comment')
 
         tracker_config = tracker['tracker_config']
-        assert_true('options' in tracker_config.keys())
+        assert_true('options' in list(tracker_config.keys()))
         assert_equal(tracker_config['options']['mount_point'], 'bugs')
 
         milestones = sorted(tracker['milestones'],
diff --git a/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py b/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py
index 68d10d4..149cc8a 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py
@@ -332,7 +332,7 @@ class TestTicketModel(TrackerTestWithModel):
 
     def test_json_parents(self):
         ticket = Ticket.new()
-        json_keys = ticket.__json__().keys()
+        json_keys = list(ticket.__json__().keys())
         assert_in('related_artifacts', json_keys)  # from Artifact
         assert_in('votes_up', json_keys)  # VotableArtifact
         assert_in('ticket_num', json_keys)  # Ticket
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index 42516c7..c39b54f 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -83,6 +83,7 @@ from forgetracker.widgets.ticket_form import TicketForm, TicketCustomField
 from forgetracker.widgets.bin_form import BinForm
 from forgetracker.widgets.ticket_search import TicketSearchResults, MassEdit, MassEditForm, MassMoveForm
 from forgetracker.widgets.admin_custom_fields import TrackerFieldAdmin, TrackerFieldDisplay
+import six
 
 log = logging.getLogger(__name__)
 
@@ -1696,7 +1697,7 @@ class TrackerAdminController(DefaultAdminController):
     @validate(W.options_admin, error_handler=options)
     def set_options(self, **kw):
         require_access(self.app, 'configure')
-        for k, v in kw.iteritems():
+        for k, v in six.iteritems(kw):
             self.app.config.options[k] = v
         flash('Options updated')
         redirect(request.referer or '/')
diff --git a/ForgeTracker/forgetracker/widgets/ticket_search.py b/ForgeTracker/forgetracker/widgets/ticket_search.py
index 44bc9da..ba0be4d 100644
--- a/ForgeTracker/forgetracker/widgets/ticket_search.py
+++ b/ForgeTracker/forgetracker/widgets/ticket_search.py
@@ -22,6 +22,7 @@ import ew.jinja2_ew as ew
 
 from allura.lib.widgets import form_fields as ffw
 from allura.lib.widgets import forms
+import six
 
 
 
@@ -47,7 +48,7 @@ class TicketSearchResults(ew_core.SimpleForm):
     def __init__(self, filters, *args, **kw):
         super(TicketSearchResults, self).__init__(*args, **kw)
         self.filters = {}
-        for name, field in filters.iteritems():
+        for name, field in six.iteritems(filters):
             self.filters[name] = options = [{
                 'value': val,
                 'label': '%s (%s)' % (val, count),
diff --git a/ForgeUserStats/forgeuserstats/controllers/userstats.py b/ForgeUserStats/forgeuserstats/controllers/userstats.py
index f151145..aa4e199 100644
--- a/ForgeUserStats/forgeuserstats/controllers/userstats.py
+++ b/ForgeUserStats/forgeuserstats/controllers/userstats.py
@@ -135,7 +135,7 @@ class ForgeUserStatsController(BaseController):
                     categories[cat] += 1
                 else:
                     categories[cat] = 1
-        categories = sorted(categories.items(),
+        categories = sorted(list(categories.items()),
                             key=lambda (x, y): y, reverse=True)
 
         ret_dict['lastmonth_logins'] = stats.getLastMonthLogins()
diff --git a/ForgeWiki/forgewiki/model/wiki.py b/ForgeWiki/forgewiki/model/wiki.py
index ef081d1..0a7c33b 100644
--- a/ForgeWiki/forgewiki/model/wiki.py
+++ b/ForgeWiki/forgewiki/model/wiki.py
@@ -258,7 +258,7 @@ class Page(VersionedArtifact, ActivityObject):
             t = {}
             for user in users:
                 t[user.username] = user.id
-            return t.values()
+            return list(t.values())
         user_ids = uniq([r.author for r in self.history().all()])
         return User.query.find({
             '_id': {'$in': user_ids},
diff --git a/fuse/accessfs.py b/fuse/accessfs.py
index a319544..ee19ba1 100644
--- a/fuse/accessfs.py
+++ b/fuse/accessfs.py
@@ -35,6 +35,7 @@ from threading import Lock
 from collections import deque
 
 import fuse
+import six
 
 log = logging.getLogger(__name__)
 
@@ -56,7 +57,7 @@ class check_access(object):
             new_kwargs = dict(kwargs)
             for i, (mode, path) in enumerate(zip(self._args, args)):
                 new_args[i] = self.check(inst, path, mode)
-            for name, mode in self._kwargs.iteritems():
+            for name, mode in six.iteritems(self._kwargs):
                 new_kwargs[name] = self.check(inst, kwargs.get(name), mode)
             return func(inst, *new_args, **new_kwargs)
         return wrapper
diff --git a/scripts/perf/benchmark-scm.py b/scripts/perf/benchmark-scm.py
index 717da23..341beb9 100755
--- a/scripts/perf/benchmark-scm.py
+++ b/scripts/perf/benchmark-scm.py
@@ -46,8 +46,8 @@ def main(opts):
         repo = hg.repository(HgUI(), six.ensure_str(opts.repo_path))
         cid = None if opts.cid == 'HEAD' else ['%s:0' % opts.cid]
         path = opts.path.strip('/')
-        filenames = repo[
-            'tip' if opts.cid == 'HEAD' else opts.cid].manifest().keys()
+        filenames = list(repo[
+            'tip' if opts.cid == 'HEAD' else opts.cid].manifest().keys())
         filenames = [
             name for name in filenames if name.startswith(('%s/' % path).lstrip('/'))]
         names = set()
diff --git a/scripts/project-import.py b/scripts/project-import.py
index 3edb71b..2ca0f23 100644
--- a/scripts/project-import.py
+++ b/scripts/project-import.py
@@ -33,6 +33,7 @@ from tg import tmpl_context as c, app_globals as g
 from allura import model as M
 from allura.lib import helpers as h
 from allura.lib.plugin import ProjectRegistrationProvider
+import six
 
 log = logging.getLogger(__name__)
 
@@ -242,12 +243,12 @@ def create_project(p, nbhd, options):
     project.notifications_disabled = True
 
     if options.ensure_tools and 'tools' in project_template:
-        for i, tool in enumerate(project_template['tools'].iterkeys()):
+        for i, tool in enumerate(six.iterkeys(project_template['tools'])):
             tool_config = project_template['tools'][tool]
             if project.app_instance(tool_config['mount_point']):
                 continue
             tool_options = tool_config.get('options', {})
-            for k, v in tool_options.iteritems():
+            for k, v in six.iteritems(tool_options):
                 if isinstance(v, basestring):
                     tool_options[k] = string.Template(v).safe_substitute(
                         project.root_project.__dict__.get('root_project', {}))
diff --git a/scripts/teamforge-import.py b/scripts/teamforge-import.py
index 7d001c6..8c2ba90 100644
--- a/scripts/teamforge-import.py
+++ b/scripts/teamforge-import.py
@@ -864,7 +864,7 @@ def get_homepage_wiki(project):
             download_file('wiki', img_url, project.id,
                           'wiki', 'homepage', filename)
 
-    for path, text in pages.iteritems():
+    for path, text in six.iteritems(pages):
         if options.default_wiki_text in text:
             log.debug('skipping default wiki page %s' % path)
         else:
@@ -1078,7 +1078,7 @@ def test_make_valid_sf_username():
         'u012345678901234567890': 'u0123456789-mmi',
         'foo^213': 'foo213-mmi'
     }
-    for k, v in tests.iteritems():
+    for k, v in six.iteritems(tests):
         assert make_valid_sf_username(k) == v
 
 
diff --git a/scripts/trac_import.py b/scripts/trac_import.py
index fda168b..10db3cf 100644
--- a/scripts/trac_import.py
+++ b/scripts/trac_import.py
@@ -23,6 +23,7 @@ from optparse import OptionParser
 
 from allura.lib.import_api import AlluraImportApiClient
 from tracwikiimporter.scripts.wiki_from_trac.loaders import import_wiki
+import six
 
 
 def main():
@@ -42,7 +43,7 @@ def main():
             user_map = json.load(f)
             if type(user_map) is not type({}):
                 raise ValueError
-            for k, v in user_map.iteritems():
+            for k, v in six.iteritems(user_map):
                 print(k, v)
                 if not isinstance(k, basestring) or not isinstance(v, basestring):
                     raise ValueError


[allura] 07/41: [#8349] python-modernize -n -w --no-diffs -f print .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 707965e8f338c109c972724bb149e76e3bd9125a
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 12:42:00 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f print .
---
 Allura/allura/command/script.py                         |  7 ++++---
 Allura/allura/command/show_models.py                    |  3 ++-
 Allura/allura/command/taskd.py                          |  3 ++-
 Allura/allura/lib/AsciiDammit.py                        | 17 +++++++++--------
 Allura/allura/scripts/create_sitemap_files.py           |  5 +++--
 Allura/allura/scripts/refresh_last_commits.py           |  9 +++++----
 Allura/allura/scripts/trac_export.py                    |  5 +++--
 Allura/allura/tests/functional/test_auth.py             |  3 ++-
 Allura/allura/tests/tscript.py                          |  3 ++-
 AlluraTest/alluratest/smtp_debug.py                     |  3 ++-
 ForgeGit/forgegit/tests/functional/test_controllers.py  |  5 +++--
 ForgeGit/forgegit/tests/model/test_repository.py        |  3 ++-
 ForgeSVN/forgesvn/tests/model/test_repository.py        |  3 ++-
 ForgeSVN/setup.py                                       |  3 ++-
 ForgeWiki/forgewiki/tests/functional/test_root.py       |  1 +
 fuse/accessfs.py                                        | 11 ++++++-----
 scripts/changelog.py                                    |  9 +++++----
 scripts/migrations/020-remove-wiki-title-slashes.py     |  5 +++--
 scripts/migrations/028-remove-svn-trees.py              |  7 ++++---
 scripts/migrations/031-set-user-pending-to-false.py     |  3 ++-
 .../032-subscribe-merge-request-submitters.py           |  3 ++-
 .../migrations/033-change-comment-anon-permissions.py   |  3 ++-
 scripts/new_ticket.py                                   | 11 ++++++-----
 scripts/perf/benchmark-scm.py                           |  7 ++++---
 scripts/perf/call_count.py                              |  9 +++++----
 scripts/perf/generate-projects.py                       |  7 ++++---
 scripts/perf/md_perf.py                                 | 17 +++++++++--------
 scripts/perf/parse_timings.py                           |  5 +++--
 scripts/perf/sstress.py                                 |  5 +++--
 scripts/perf/test_git_lcd.py                            |  5 +++--
 scripts/teamforge-import.py                             |  3 ++-
 scripts/trac_import.py                                  |  7 ++++---
 scripts/wiki-copy.py                                    | 15 ++++++++-------
 33 files changed, 119 insertions(+), 86 deletions(-)

diff --git a/Allura/allura/command/script.py b/Allura/allura/command/script.py
index de77136..29e030b 100644
--- a/Allura/allura/command/script.py
+++ b/Allura/allura/command/script.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import sys
 import os.path
 import cProfile
@@ -86,10 +87,10 @@ class SetToolAccessCommand(base.Command):
                        ' so removing from list.')
                 continue
             if s not in ('alpha', 'beta'):
-                print 'Unknown tool status %s' % s
+                print('Unknown tool status %s' % s)
                 sys.exit(1)
             extra_status.append(s)
-        print 'Setting project "%s" tool access to production + %r' % (
-            self.args[1], extra_status)
+        print('Setting project "%s" tool access to production + %r' % (
+            self.args[1], extra_status))
         c.project._extra_tool_status = extra_status
         session(c.project).flush()
diff --git a/Allura/allura/command/show_models.py b/Allura/allura/command/show_models.py
index 8417bb2..c9ad171 100644
--- a/Allura/allura/command/show_models.py
+++ b/Allura/allura/command/show_models.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import sys
 from collections import defaultdict
 from contextlib import contextmanager
@@ -47,7 +48,7 @@ class ShowModelsCommand(base.Command):
         graph = build_model_inheritance_graph()
         for depth, cls in dfs(MappedClass, graph):
             for line in dump_cls(depth, cls):
-                print line
+                print(line)
 
 
 class ReindexCommand(base.Command):
diff --git a/Allura/allura/command/taskd.py b/Allura/allura/command/taskd.py
index 5eb2559..34c7e6b 100644
--- a/Allura/allura/command/taskd.py
+++ b/Allura/allura/command/taskd.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import logging
 import os
 import time
@@ -193,7 +194,7 @@ class TaskCommand(base.Command):
         else:
             q = dict(state=self.options.state)
         for t in M.MonQTask.query.find(q):
-            print t
+            print(t)
 
     def _retry(self):
         '''Retry tasks in an error state'''
diff --git a/Allura/allura/lib/AsciiDammit.py b/Allura/allura/lib/AsciiDammit.py
index ea27a9f..80b1154 100644
--- a/Allura/allura/lib/AsciiDammit.py
+++ b/Allura/allura/lib/AsciiDammit.py
@@ -18,6 +18,7 @@ all rights in this work otherwise reserved under copyright.
 """
 
 from __future__ import unicode_literals
+from __future__ import print_function
 __author__ = "Leonard Richardson (leonardr@segfault.org)"
 __version__ = "$Revision: 1.3 $"
 __date__ = "$Date: 2009/04/28 10:45:03 $"
@@ -214,11 +215,11 @@ def demoronise(t):
 if __name__ == '__main__':
 
     french = b'\x93Sacr\xe9 bleu!\x93'
-    print "First we mangle some French."
-    print asciiDammit(french)
-    print htmlDammit(french)
-
-    print
-    print "And now we fix the MS-quotes but leave the French alone."
-    print demoronise(french)
-    print htmlDammit(french, 1)
+    print("First we mangle some French.")
+    print(asciiDammit(french))
+    print(htmlDammit(french))
+
+    print()
+    print("And now we fix the MS-quotes but leave the French alone.")
+    print(demoronise(french))
+    print(htmlDammit(french, 1))
diff --git a/Allura/allura/scripts/create_sitemap_files.py b/Allura/allura/scripts/create_sitemap_files.py
index f20645a..1fbe03a 100644
--- a/Allura/allura/scripts/create_sitemap_files.py
+++ b/Allura/allura/scripts/create_sitemap_files.py
@@ -29,6 +29,7 @@ things that would make it faster, if we need/want to.
 """
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import os
 from datetime import datetime
 import argparse
@@ -118,8 +119,8 @@ class CreateSitemapFiles(ScriptTask):
                                      'date': p.last_updated.strftime("%Y-%m-%d")})
 
                 except Exception as e:
-                    print "Error creating sitemap for project '%s': %s" %\
-                        (p.shortname, e)
+                    print("Error creating sitemap for project '%s': %s" %\
+                        (p.shortname, e))
                 creds.clear()
                 if len(locs) >= options.urls_per_file:
                     write_sitemap(locs[:options.urls_per_file], file_count)
diff --git a/Allura/allura/scripts/refresh_last_commits.py b/Allura/allura/scripts/refresh_last_commits.py
index 01e2b8f..71a729e 100644
--- a/Allura/allura/scripts/refresh_last_commits.py
+++ b/Allura/allura/scripts/refresh_last_commits.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import argparse
 import logging
 from datetime import datetime
@@ -141,11 +142,11 @@ class RefreshLastCommits(ScriptTask):
         )
         c.model_cache = model_cache
         timings = []
-        print 'Processing last commits'
+        print('Processing last commits')
         for i, commit_id in enumerate(commit_ids):
             commit = M.repository.Commit.query.get(_id=commit_id)
             if commit is None:
-                print "Commit missing, skipping: %s" % commit_id
+                print("Commit missing, skipping: %s" % commit_id)
                 continue
             commit.set_context(c.app.repo)
             with time(timings):
@@ -188,8 +189,8 @@ class RefreshLastCommits(ScriptTask):
         tt = sum(timings)
         at = tt / len(timings)
         mat = sum(timings[-debug_step:]) / debug_step
-        print '  Processed %d commits (max: %f, avg: %f, mavg: %f, tot: %f)' % (
-            processed, mt, at, mat, tt)
+        print('  Processed %d commits (max: %f, avg: %f, mavg: %f, tot: %f)' % (
+            processed, mt, at, mat, tt))
 
 
 @contextmanager
diff --git a/Allura/allura/scripts/trac_export.py b/Allura/allura/scripts/trac_export.py
index 7ad2277..f302186 100644
--- a/Allura/allura/scripts/trac_export.py
+++ b/Allura/allura/scripts/trac_export.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import logging
 import sys
 import csv
@@ -122,7 +123,7 @@ class TracExport(object):
     def log_url(self, url):
         log.info(url)
         if self.verbose:
-            print >>sys.stderr, url
+            print(url, file=sys.stderr)
 
     @classmethod
     def trac2z_date(cls, s):
@@ -227,7 +228,7 @@ class TracExport(object):
         f = self.csvopen(url)
         reader = csv.DictReader(f)
         fields = reader.next()
-        print fields
+        print(fields)
         return int(fields['id'])
 
     def get_ticket(self, id, extra={}):
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index 64ba3e7..e48921d 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import calendar
 from datetime import datetime, time, timedelta
 from time import time as time_time
@@ -599,7 +600,7 @@ class TestAuth(TestController):
                       params=change_params)
 
         u = M.User.by_username('test-admin')
-        print(u.get_tool_data('AuthPasswordReset', 'hash'))
+        print((u.get_tool_data('AuthPasswordReset', 'hash')))
         assert_equal(u.get_tool_data('AuthPasswordReset', 'hash'), '')
         assert_equal(u.get_tool_data('AuthPasswordReset', 'hash_expiry'), '')
 
diff --git a/Allura/allura/tests/tscript.py b/Allura/allura/tests/tscript.py
index 022a710..2f2be0f 100644
--- a/Allura/allura/tests/tscript.py
+++ b/Allura/allura/tests/tscript.py
@@ -16,13 +16,14 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import logging
 
 from allura import model as M
 
 log = logging.getLogger(__name__)
 
-print 'In a script'
+print('In a script')
 log.info('in a script')
 
 for p in M.Project.query.find():
diff --git a/AlluraTest/alluratest/smtp_debug.py b/AlluraTest/alluratest/smtp_debug.py
index 3019e9f..5c9f037 100644
--- a/AlluraTest/alluratest/smtp_debug.py
+++ b/AlluraTest/alluratest/smtp_debug.py
@@ -18,11 +18,12 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 from smtpd import DebuggingServer
 
 
 class BetterDebuggingServer(DebuggingServer, object):
 
     def process_message(self, peer, mailfrom, rcpttos, data):
-        print 'TO: ' + ', '.join(rcpttos)
+        print('TO: ' + ', '.join(rcpttos))
         super(BetterDebuggingServer, self).process_message(peer, mailfrom, rcpttos, data)
\ No newline at end of file
diff --git a/ForgeGit/forgegit/tests/functional/test_controllers.py b/ForgeGit/forgegit/tests/functional/test_controllers.py
index 366e129..89665e4 100644
--- a/ForgeGit/forgegit/tests/functional/test_controllers.py
+++ b/ForgeGit/forgegit/tests/functional/test_controllers.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import json
 import re
 import os
@@ -576,9 +577,9 @@ class TestFork(_TestCase):
 
     def _follow(self, r, **kw):
         if r.status_int == 302:
-            print r.request.url
+            print(r.request.url)
         while r.status_int == 302:
-            print ' ==> 302 ==> %s' % r.location
+            print(' ==> 302 ==> %s' % r.location)
             r = r.follow(**kw)
         return r
 
diff --git a/ForgeGit/forgegit/tests/model/test_repository.py b/ForgeGit/forgegit/tests/model/test_repository.py
index fed9243..df7d91e 100644
--- a/ForgeGit/forgegit/tests/model/test_repository.py
+++ b/ForgeGit/forgegit/tests/model/test_repository.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import os
 import shutil
 import stat
@@ -1054,7 +1055,7 @@ class TestGitCommit(unittest.TestCase):
                  + self.rev.diffs.changed
                  + self.rev.diffs.copied)
         for d in diffs:
-            print d
+            print(d)
 
     def test_log(self):
         # path only
diff --git a/ForgeSVN/forgesvn/tests/model/test_repository.py b/ForgeSVN/forgesvn/tests/model/test_repository.py
index 3135697..322bcd2 100644
--- a/ForgeSVN/forgesvn/tests/model/test_repository.py
+++ b/ForgeSVN/forgesvn/tests/model/test_repository.py
@@ -17,6 +17,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import os
 import shutil
 import unittest
@@ -601,7 +602,7 @@ class TestSVNRev(unittest.TestCase):
                  + self.rev.diffs.changed
                  + self.rev.diffs.copied)
         for d in diffs:
-            print d
+            print(d)
 
     def _oid(self, rev_id):
         return '%s:%s' % (self.repo._id, rev_id)
diff --git a/ForgeSVN/setup.py b/ForgeSVN/setup.py
index 0a0314a..c0409b7 100644
--- a/ForgeSVN/setup.py
+++ b/ForgeSVN/setup.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 from setuptools import setup, find_packages
 
 from forgesvn.version import __version__
@@ -26,7 +27,7 @@ from forgesvn.version import __version__
 try:
     import pysvn
 except ImportError:
-    print '\npysvn must be installed for ForgeSVN to work\n'
+    print('\npysvn must be installed for ForgeSVN to work\n')
     raise
 
 setup(name='ForgeSVN',
diff --git a/ForgeWiki/forgewiki/tests/functional/test_root.py b/ForgeWiki/forgewiki/tests/functional/test_root.py
index 8bba3a2..16b529f 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_root.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_root.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import os
 import StringIO
 import allura
diff --git a/fuse/accessfs.py b/fuse/accessfs.py
index 62808ea..f004b0e 100644
--- a/fuse/accessfs.py
+++ b/fuse/accessfs.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import os
 import json
 import urllib
@@ -102,7 +103,7 @@ class AccessFS(fuse.Fuse):
         return os.readlink("." + path)
 
     def readdir(self, path, offset):
-        print 'Readdir!'
+        print('Readdir!')
         for e in os.listdir("." + path):
             yield fuse.Direntry(e)
 
@@ -312,7 +313,7 @@ class PermissionCache(object):
             entry, timestamp = self._data[uid, path]
             elapsed = time.time() - timestamp
             if elapsed > self._timeout:
-                print 'Timeout!', elapsed
+                print('Timeout!', elapsed)
                 uname = self._uid_cache.get(uid)
                 entry = self._refresh_result(
                     uid, path, self._api_lookup(uname, path))
@@ -339,10 +340,10 @@ class PermissionCache(object):
             + urllib.urlencode(dict(
                 repo_path=path,
                 username=uname)))
-        print 'Checking access for %s at %s (%s)' % (uname, url, path)
+        print('Checking access for %s at %s (%s)' % (uname, url, path))
         fp = urllib2.urlopen(url)
         result = json.load(fp)
-        print result
+        print(result)
         entry = 0
         if result['allow_read']:
             entry |= os.R_OK
@@ -414,7 +415,7 @@ Userspace nullfs-alike: mirror the filesystem tree from some point on.
         if server.fuse_args.mount_expected():
             os.chdir(server.root)
     except OSError:
-        print >> sys.stderr, "can't enter root of underlying filesystem"
+        print("can't enter root of underlying filesystem", file=sys.stderr)
         sys.exit(1)
 
     server.main()
diff --git a/scripts/changelog.py b/scripts/changelog.py
index 13300fd..bf803b8 100755
--- a/scripts/changelog.py
+++ b/scripts/changelog.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import sys
 import re
 import git
@@ -65,14 +66,14 @@ def get_ticket_summaries(tickets):
 
 
 def print_changelog(version, summaries, changes_without_tickets):
-    print 'Version {version}  ({date})\n'.format(**{
+    print('Version {version}  ({date})\n'.format(**{
         'version': version,
         'date': datetime.utcnow().strftime('%B %Y'),
-    })
+    }))
     for ticket in sorted(summaries.keys()):
-        print " * [#{0}] {1}".format(ticket, summaries[ticket].encode('utf-8'))
+        print(" * [#{0}] {1}".format(ticket, summaries[ticket].encode('utf-8')))
     for change in changes_without_tickets:
-        print " * {}".format(change.encode('utf-8'))
+        print(" * {}".format(change.encode('utf-8')))
 
 if __name__ == '__main__':
     main()
diff --git a/scripts/migrations/020-remove-wiki-title-slashes.py b/scripts/migrations/020-remove-wiki-title-slashes.py
index 00c314a..c7bbea8 100644
--- a/scripts/migrations/020-remove-wiki-title-slashes.py
+++ b/scripts/migrations/020-remove-wiki-title-slashes.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import logging
 
 from tg import tmpl_context as c
@@ -30,10 +31,10 @@ log = logging.getLogger(__name__)
 def main():
     c.project = None
     pages = WM.Page.query.find({'title': {'$regex': '\/'}}).all()
-    print 'Found %s wiki titles containing "/"...' % len(pages)
+    print('Found %s wiki titles containing "/"...' % len(pages))
     for page in pages:
         page.title = page.title.replace('/', '-')
-        print 'Updated: %s' % page.title
+        print('Updated: %s' % page.title)
     ThreadLocalORMSession.flush_all()
 
 if __name__ == '__main__':
diff --git a/scripts/migrations/028-remove-svn-trees.py b/scripts/migrations/028-remove-svn-trees.py
index 4023106..f0ba538 100644
--- a/scripts/migrations/028-remove-svn-trees.py
+++ b/scripts/migrations/028-remove-svn-trees.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import logging
 
 from ming.orm import ThreadLocalORMSession
@@ -34,16 +35,16 @@ def kill_tree(repo, commit_id, path, tree):
         tid = repo._tree_oid(commit_id, path + '/' + tree_rec.name)
         child_tree = M.repository.Tree.query.get(_id=tid)
         if child_tree:
-            print '  Found {0}'.format((path + '/' + tree_rec.name).encode('utf8'))
+            print('  Found {0}'.format((path + '/' + tree_rec.name).encode('utf8')))
             kill_tree(repo, commit_id, path + '/' + tree_rec.name, child_tree)
         else:
-            print '  Missing {0}'.format((path + '/' + tree_rec.name).encode('utf8'))
+            print('  Missing {0}'.format((path + '/' + tree_rec.name).encode('utf8')))
 
 
 def main():
     for chunk in utils.chunked_find(SM.Repository):
         for r in chunk:
-            print 'Processing {0}'.format(r)
+            print('Processing {0}'.format(r))
             all_commit_ids = r._impl.all_commit_ids()
             if all_commit_ids:
                 for commit in M.repository.Commit.query.find({'_id': {'$in': all_commit_ids}}):
diff --git a/scripts/migrations/031-set-user-pending-to-false.py b/scripts/migrations/031-set-user-pending-to-false.py
index d243e8b..ef0c67e 100644
--- a/scripts/migrations/031-set-user-pending-to-false.py
+++ b/scripts/migrations/031-set-user-pending-to-false.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import logging
 
 from ming.odm import ThreadLocalORMSession, state
@@ -29,7 +30,7 @@ log = logging.getLogger(__name__)
 def main():
     for chunk in utils.chunked_find(M.User):
         for user in chunk:
-            print 'Processing {0}'.format(user.username)
+            print('Processing {0}'.format(user.username))
             user.pending = False
             # Ming doesn't mark document for update, since pending is False
             # by default, even if field is missing from mongo
diff --git a/scripts/migrations/032-subscribe-merge-request-submitters.py b/scripts/migrations/032-subscribe-merge-request-submitters.py
index 57aa778..791cf3c 100644
--- a/scripts/migrations/032-subscribe-merge-request-submitters.py
+++ b/scripts/migrations/032-subscribe-merge-request-submitters.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import logging
 
 from ming.odm import ThreadLocalORMSession, state
@@ -30,7 +31,7 @@ def main():
     for chunk in utils.chunked_find(M.MergeRequest):
         for mr in chunk:
             try:
-                print 'Processing {0}'.format(mr.url())
+                print('Processing {0}'.format(mr.url()))
                 mr.subscribe(user=mr.creator)
                 ThreadLocalORMSession.flush_all()
             except:
diff --git a/scripts/migrations/033-change-comment-anon-permissions.py b/scripts/migrations/033-change-comment-anon-permissions.py
index 2dad964..a418a1b 100644
--- a/scripts/migrations/033-change-comment-anon-permissions.py
+++ b/scripts/migrations/033-change-comment-anon-permissions.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import sys
 import logging
 from ming.orm import ThreadLocalORMSession, session
@@ -58,7 +59,7 @@ def main():
                         anon_role_id = acl.role_id
 
                 if anon_role_id:
-                    print "revoking anon moderate privelege for '{}'".format(p._id)
+                    print("revoking anon moderate privelege for '{}'".format(p._id))
                     security.simple_revoke(p.acl, anon_role_id, 'moderate')
                     session(p).flush(p)
 
diff --git a/scripts/new_ticket.py b/scripts/new_ticket.py
index 86c6ca8..8574220 100755
--- a/scripts/new_ticket.py
+++ b/scripts/new_ticket.py
@@ -17,6 +17,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import sys
 import argparse
 import requests
@@ -43,10 +44,10 @@ if __name__ == '__main__':
     opts = get_opts()
     access_token = raw_input('Access (bearer) token: ')
     summary = raw_input('Summary: ')
-    print 'Description (C-d to end):'
-    print '-----------------------------------------------'
+    print('Description (C-d to end):')
+    print('-----------------------------------------------')
     description = sys.stdin.read()
-    print '-----------------------------------------------'
+    print('-----------------------------------------------')
 
     r = requests.post(opts.url, params={
         'access_token': access_token,
@@ -54,7 +55,7 @@ if __name__ == '__main__':
         'ticket_form.description': description,
     })
     if r.status_code == 200:
-        print 'Ticket created at: %s' % r.url
+        print('Ticket created at: %s' % r.url)
         pprint(r.json())
     else:
-        print 'Error [%s]:\n%s' % (r.status_code, r.text)
+        print('Error [%s]:\n%s' % (r.status_code, r.text))
diff --git a/scripts/perf/benchmark-scm.py b/scripts/perf/benchmark-scm.py
index f1d8e83..9bb8697 100755
--- a/scripts/perf/benchmark-scm.py
+++ b/scripts/perf/benchmark-scm.py
@@ -19,6 +19,7 @@
 
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import os
 import sys
 import argparse
@@ -73,9 +74,9 @@ def main(opts):
         impl(repo, cid, path, names, opts.repo_path)
         end = datetime.now()
         total += (end - start).total_seconds()
-    print
-    print 'Total time:           %s' % total
-    print 'Average time per run: %s' % (total / opts.count)
+    print()
+    print('Total time:           %s' % total)
+    print('Average time per run: %s' % (total / opts.count))
 
 
 def impl_git_tree(repo, cid, path, names, *args):
diff --git a/scripts/perf/call_count.py b/scripts/perf/call_count.py
index c424d82..658e3db 100755
--- a/scripts/perf/call_count.py
+++ b/scripts/perf/call_count.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import argparse
 import json
 import logging
@@ -69,7 +70,7 @@ def main(args):
 
     counts = count_page(test, url, verbose=args.verbose,
                         debug_html=args.debug_html)
-    print json.dumps(counts)
+    print(json.dumps(counts))
     write_csv(counts, args.id, args.data_file)
     test.tearDown()
 
@@ -117,17 +118,17 @@ def count_page(test, url, verbose=False, debug_html=False):
 
     with LogCapture('stats') as stats, LogCapture('timermiddleware') as calls:
         resp = test.app.get(url, extra_environ=dict(username=str('*anonymous')))
-        print url, resp.status
+        print(url, resp.status)
         if debug_html:
             debug_filename = 'call-{}.html'.format(''.join([random.choice(string.ascii_letters + string.digits)
                                                    for n in xrange(10)]))
             with open(debug_filename, 'w') as out:
                 out.write(resp.body)
-            print debug_filename
+            print(debug_filename)
 
     if verbose:
         for r in calls.records:
-            print r.getMessage()
+            print(r.getMessage())
 
     assert len(stats.records) == 1
     timings = json.loads(stats.records[0].getMessage())
diff --git a/scripts/perf/generate-projects.py b/scripts/perf/generate-projects.py
index 74d83ad..0b60da3 100644
--- a/scripts/perf/generate-projects.py
+++ b/scripts/perf/generate-projects.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import re
 from ming.odm import ThreadLocalORMSession
 from allura import model as M
@@ -29,10 +30,10 @@ def main(start, cnt):
         name = 'gen-proj-{}'.format(i)
         project = n.register_project(name, admin)
         if (i-start) > 0 and (i-start) % 100 == 0:
-            print 'Created {} projects'.format(i-start)
-    print 'Flushing...'
+            print('Created {} projects'.format(i-start))
+    print('Flushing...')
     ThreadLocalORMSession.flush_all()
-    print 'Done'
+    print('Done')
 
 if __name__ == '__main__':
     import sys
diff --git a/scripts/perf/md_perf.py b/scripts/perf/md_perf.py
index baee3f5..63e8fac 100644
--- a/scripts/perf/md_perf.py
+++ b/scripts/perf/md_perf.py
@@ -46,6 +46,7 @@ sys     0m1.112s
 """
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import argparse
 import cProfile
 import time
@@ -86,24 +87,24 @@ def main(opts):
 
 def render(artifact, md, opts):
     start = begin = time.time()
-    print "%4s %20s %10s %s" % ('', 'Conversion Time (s)', 'Text Size', 'Post._id')
+    print("%4s %20s %10s %s" % ('', 'Conversion Time (s)', 'Text Size', 'Post._id'))
     for i, p in enumerate(artifact.discussion_thread.posts):
         text = DUMMYTEXT or p.text
         if opts.n and i + 1 not in opts.n:
-            print 'Skipping post %s' % str(i + 1)
+            print('Skipping post %s' % str(i + 1))
             continue
         if opts.profile:
-            print 'Profiling post %s' % str(i + 1)
+            print('Profiling post %s' % str(i + 1))
             cProfile.runctx('output = md.convert(text)', globals(), locals())
         else:
             output = md.convert(text)
         elapsed = time.time() - start
-        print "%4s %1.18f %10s %s" % (i + 1, elapsed, len(text), p._id)
+        print("%4s %1.18f %10s %s" % (i + 1, elapsed, len(text), p._id))
         if opts.output:
-            print 'Input:', text[:min(300, len(text))]
-            print 'Output:', output[:min(MAX_OUTPUT, len(output))]
+            print('Input:', text[:min(300, len(text))])
+            print('Output:', output[:min(MAX_OUTPUT, len(output))])
         start = time.time()
-    print "Total time:", start - begin
+    print("Total time:", start - begin)
     return output
 
 
@@ -129,4 +130,4 @@ if __name__ == '__main__':
     if opts.compare:
         opts.re2 = not opts.re2
         out2 = main(opts)
-        print 're/re2 outputs match: ', out1 == out2
+        print('re/re2 outputs match: ', out1 == out2)
diff --git a/scripts/perf/parse_timings.py b/scripts/perf/parse_timings.py
index 9bda703..706482f 100644
--- a/scripts/perf/parse_timings.py
+++ b/scripts/perf/parse_timings.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import json
 from datetime import datetime
 import argparse
@@ -52,6 +53,6 @@ for line in args.input_file:
 
 timings.sort()  # in case of multiple input files
 
-print '\t'.join(['Time'] + args.timings)
+print('\t'.join(['Time'] + args.timings))
 for t in timings:
-    print '\t'.join(map(str, t))
+    print('\t'.join(map(str, t)))
diff --git a/scripts/perf/sstress.py b/scripts/perf/sstress.py
index 475a975..332edfd 100644
--- a/scripts/perf/sstress.py
+++ b/scripts/perf/sstress.py
@@ -22,6 +22,7 @@ sstress - an SMTP stress testing tool
 '''
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import smtplib
 import threading
 import time
@@ -44,8 +45,8 @@ def main():
         t.join()
     end = time.time()
     elapsed = end - begin
-    print '%d requests completed in %f seconds' % (N, elapsed)
-    print '%f requests/second' % (N / elapsed)
+    print('%d requests completed in %f seconds' % (N, elapsed))
+    print('%f requests/second' % (N / elapsed))
 
 
 def stress():
diff --git a/scripts/perf/test_git_lcd.py b/scripts/perf/test_git_lcd.py
index c992aa8..1557aca 100644
--- a/scripts/perf/test_git_lcd.py
+++ b/scripts/perf/test_git_lcd.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import sys
 import os
 from glob import glob
@@ -43,11 +44,11 @@ def main(repo_dir, sub_dir='', commit=None):
     commit = Mock(_id=commit or git.head)
     paths = glob(os.path.join(repo_dir, sub_dir, '*'))
     paths = [path.replace(repo_dir + '/', '', 1) for path in paths]
-    print "Timing LCDs for %s at %s" % (paths, commit._id)
+    print("Timing LCDs for %s at %s" % (paths, commit._id))
     with benchmark() as timer:
         result = git.last_commit_ids(commit, paths)
     pprint(result)
-    print "Took %f seconds" % timer['result']
+    print("Took %f seconds" % timer['result'])
 
 if __name__ == '__main__':
     main(*sys.argv[1:])
diff --git a/scripts/teamforge-import.py b/scripts/teamforge-import.py
index ed920ad..b6d04c5 100644
--- a/scripts/teamforge-import.py
+++ b/scripts/teamforge-import.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import logging
 from getpass import getpass
 from optparse import OptionParser
@@ -134,7 +135,7 @@ def main():
         project_ids = [p.id for p in projects.dataRows]
 
     if options.list_project_ids:
-        print ' '.join(project_ids)
+        print(' '.join(project_ids))
         return
 
     if not os.path.exists(options.output_dir):
diff --git a/scripts/trac_import.py b/scripts/trac_import.py
index 55938ac..ad070a7 100644
--- a/scripts/trac_import.py
+++ b/scripts/trac_import.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import json
 from optparse import OptionParser
 
@@ -41,7 +42,7 @@ def main():
             if type(user_map) is not type({}):
                 raise ValueError
             for k, v in user_map.iteritems():
-                print k, v
+                print(k, v)
                 if not isinstance(k, basestring) or not isinstance(v, basestring):
                     raise ValueError
         except ValueError:
@@ -72,10 +73,10 @@ def import_forum(cli, project, tool, user_map, doc_txt, validate=True,
             )
     if validate:
         url += '/validate_import'
-        print cli.call(url, doc=doc_txt, user_map=json.dumps(user_map))
+        print(cli.call(url, doc=doc_txt, user_map=json.dumps(user_map)))
     else:
         url += '/perform_import'
-        print cli.call(url, doc=doc_txt, user_map=json.dumps(user_map))
+        print(cli.call(url, doc=doc_txt, user_map=json.dumps(user_map)))
 
 
 def parse_options():
diff --git a/scripts/wiki-copy.py b/scripts/wiki-copy.py
index bfceec3..f557445 100644
--- a/scripts/wiki-copy.py
+++ b/scripts/wiki-copy.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import print_function
 import os
 import sys
 import urllib
@@ -53,17 +54,17 @@ def main():
             page_data = urllib.urlopen(from_url).read()
             page_json = json.loads(page_data)
             if options.debug:
-                print page_json['text']
+                print(page_json['text'])
                 break
             resp = oauth_client.request(
                 to_url, 'POST', body=urllib.urlencode(dict(text=page_json['text'].encode('utf-8'))))
             if resp[0]['status'] == '200':
-                print "Posted {0} to {1}".format(page_json['title'], to_url)
+                print("Posted {0} to {1}".format(page_json['title'], to_url))
             else:
-                print "Error posting {0} to {1}: {2} (project may not exist)".format(page_json['title'], to_url, resp[0]['status'])
+                print("Error posting {0} to {1}: {2} (project may not exist)".format(page_json['title'], to_url, resp[0]['status']))
                 break
         except:
-            print "Error processing " + p
+            print("Error processing " + p)
             raise
 
 
@@ -97,7 +98,7 @@ def make_oauth_client(base_url):
             AUTHORIZE_URL, request_token['oauth_token'])
         if getattr(webbrowser.get(), 'name', '') == 'links':
             # sandboxes
-            print("Go to %s" % pin_url)
+            print(("Go to %s" % pin_url))
         else:
             webbrowser.open(pin_url)
         oauth_verifier = raw_input('What is the PIN? ')
@@ -116,8 +117,8 @@ def make_oauth_client(base_url):
 
     # save oauth token for later use
     cp.write(open(config_file, 'w'))
-    print 'Saving oauth tokens in {} for later re-use'.format(config_file)
-    print
+    print('Saving oauth tokens in {} for later re-use'.format(config_file))
+    print()
 
     access_token = oauth.Token(oauth_token, oauth_token_secret)
     oauth_client = oauth.Client(consumer, access_token)


[allura] 36/41: [#8349] python-modernize -n -w --no-diffs -f renames .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit f946c4d984b0f55bfa3028e5fbac8b5ea6f1f4cc
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 17:00:04 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f renames .
---
 Allura/allura/lib/helpers.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index 8f075eb..13c14a8 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -678,7 +678,7 @@ def twophase_transaction(*engines):
         raise
 
 
-def paging_sanitizer(limit, page, total_count=sys.maxint, zero_based_pages=True):
+def paging_sanitizer(limit, page, total_count=sys.maxsize, zero_based_pages=True):
     """Return limit, page - both converted to int and constrained to
     valid ranges based on total_count.
 


[allura] 27/41: [#8349] python-modernize -n -w --no-diffs -f tuple_params .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit a50dd4e20b07f4b7d3994c6a7ae5b38641733c1a
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 15:17:49 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f tuple_params .
---
 Allura/allura/lib/utils.py                             | 2 +-
 Allura/allura/lib/widgets/forms.py                     | 2 +-
 ForgeUserStats/forgeuserstats/controllers/userstats.py | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Allura/allura/lib/utils.py b/Allura/allura/lib/utils.py
index 5439482..7cf1526 100644
--- a/Allura/allura/lib/utils.py
+++ b/Allura/allura/lib/utils.py
@@ -193,7 +193,7 @@ def chunked_list(l, n):
 def chunked_iter(iterable, max_size):
     '''return iterable 'chunks' from the iterable of max size max_size'''
     eiter = enumerate(iterable)
-    keyfunc = lambda (i, x): i // max_size
+    keyfunc = lambda i_x: i_x[0] // max_size
     for _, chunk in groupby(eiter, keyfunc):
         yield (x for i, x in chunk)
 
diff --git a/Allura/allura/lib/widgets/forms.py b/Allura/allura/lib/widgets/forms.py
index 45d4a7d..0c911c0 100644
--- a/Allura/allura/lib/widgets/forms.py
+++ b/Allura/allura/lib/widgets/forms.py
@@ -263,7 +263,7 @@ class PersonalDataForm(ForgeForm):
                 options=[ew.Option(py_value=" ", label=" -- Unknown -- ", selected=False)] +
                         [ew.Option(py_value=c, label=n, selected=False)
                          for c, n in sorted(list(country_names.items()),
-                                            key=lambda (k, v): v)],
+                                            key=lambda k_v: k_v[1])],
                 attrs={'onchange': 'selectTimezone(this.value)'}),
             ew.TextField(
                 name='city',
diff --git a/ForgeUserStats/forgeuserstats/controllers/userstats.py b/ForgeUserStats/forgeuserstats/controllers/userstats.py
index aa4e199..36818ae 100644
--- a/ForgeUserStats/forgeuserstats/controllers/userstats.py
+++ b/ForgeUserStats/forgeuserstats/controllers/userstats.py
@@ -136,7 +136,7 @@ class ForgeUserStatsController(BaseController):
                 else:
                     categories[cat] = 1
         categories = sorted(list(categories.items()),
-                            key=lambda (x, y): y, reverse=True)
+                            key=lambda x_y: x_y[1], reverse=True)
 
         ret_dict['lastmonth_logins'] = stats.getLastMonthLogins()
         ret_dict['categories'] = categories


[allura] 22/41: [#8349] python-modernize -n -w --no-diffs -f zip .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 0b42e8d21acadb19eb16b9e44222707575f74a3f
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 14:40:29 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f zip .
---
 Allura/allura/controllers/auth.py                            | 1 +
 Allura/allura/lib/utils.py                                   | 1 +
 Allura/allura/tests/functional/test_home.py                  | 1 +
 ForgeGit/forgegit/model/git_repo.py                          | 1 +
 ForgeImporters/forgeimporters/tests/github/test_extractor.py | 7 ++++---
 fuse/accessfs.py                                             | 1 +
 6 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 145eeab..132fdd3 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -58,6 +58,7 @@ from allura.lib import utils
 from allura.controllers import BaseController
 from allura.tasks.mail_tasks import send_system_mail_to_user
 import six
+from six.moves import zip
 
 log = logging.getLogger(__name__)
 
diff --git a/Allura/allura/lib/utils.py b/Allura/allura/lib/utils.py
index 5485966..49151ef 100644
--- a/Allura/allura/lib/utils.py
+++ b/Allura/allura/lib/utils.py
@@ -61,6 +61,7 @@ from ming.odm.odmsession import ODMCursor
 from ming.odm import session
 import six
 from six.moves import range
+from six.moves import zip
 
 MARKDOWN_EXTENSIONS = ['.markdown', '.mdown', '.mkdn', '.mkd', '.md']
 
diff --git a/Allura/allura/tests/functional/test_home.py b/Allura/allura/tests/functional/test_home.py
index 71b3c7e..dc523c2 100644
--- a/Allura/allura/tests/functional/test_home.py
+++ b/Allura/allura/tests/functional/test_home.py
@@ -30,6 +30,7 @@ from allura.tests import TestController
 from allura.tests import decorators as td
 from allura import model as M
 from six.moves import range
+from six.moves import zip
 
 
 class TestProjectHome(TestController):
diff --git a/ForgeGit/forgegit/model/git_repo.py b/ForgeGit/forgegit/model/git_repo.py
index 513b0cc..c49fbad 100644
--- a/ForgeGit/forgegit/model/git_repo.py
+++ b/ForgeGit/forgegit/model/git_repo.py
@@ -41,6 +41,7 @@ from allura.lib import helpers as h
 from allura.model.repository import topological_sort, prefix_paths_union
 from allura import model as M
 from io import open
+from six.moves import zip
 
 log = logging.getLogger(__name__)
 
diff --git a/ForgeImporters/forgeimporters/tests/github/test_extractor.py b/ForgeImporters/forgeimporters/tests/github/test_extractor.py
index 52167c3..617e56b 100644
--- a/ForgeImporters/forgeimporters/tests/github/test_extractor.py
+++ b/ForgeImporters/forgeimporters/tests/github/test_extractor.py
@@ -28,6 +28,7 @@ from ... import github
 # Can't use cStringIO here, because we cannot set attributes or subclass it,
 # and this is needed in mocked_urlopen below
 from StringIO import StringIO
+from six.moves import zip
 
 
 class TestGitHubProjectExtractor(TestCase):
@@ -112,9 +113,9 @@ class TestGitHubProjectExtractor(TestCase):
 
     def test_iter_issues(self):
         issues = list(self.extractor.iter_issues())
-        all_issues = zip((1, 2), self.CLOSED_ISSUES_LIST)
-        all_issues += zip((3, 4, 5), self.OPENED_ISSUES_LIST)
-        all_issues += zip((6, 7, 8), self.OPENED_ISSUES_LIST_PAGE2)
+        all_issues = list(zip((1, 2), self.CLOSED_ISSUES_LIST))
+        all_issues += list(zip((3, 4, 5), self.OPENED_ISSUES_LIST))
+        all_issues += list(zip((6, 7, 8), self.OPENED_ISSUES_LIST_PAGE2))
         self.assertEqual(issues, all_issues)
 
     def test_iter_comments(self):
diff --git a/fuse/accessfs.py b/fuse/accessfs.py
index 2a2a7f8..698693e 100644
--- a/fuse/accessfs.py
+++ b/fuse/accessfs.py
@@ -37,6 +37,7 @@ from collections import deque
 import fuse
 import six
 from io import open
+from six.moves import zip
 
 log = logging.getLogger(__name__)
 


[allura] 39/41: [#8349] python-modernize -n -w --no-diffs -f methodattrs .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 1dd19cbed9c79752801bc48d88565bfc12680450
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 17:02:56 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f methodattrs .
---
 Allura/allura/lib/patches.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Allura/allura/lib/patches.py b/Allura/allura/lib/patches.py
index 743c2f2..9f4e5fa 100644
--- a/Allura/allura/lib/patches.py
+++ b/Allura/allura/lib/patches.py
@@ -68,7 +68,7 @@ def apply():
                 override_mapping = request._override_mapping
             except AttributeError:
                 override_mapping = request._override_mapping = {}
-            override_mapping[controller.im_func] = {content_type: template}
+            override_mapping[controller.__func__] = {content_type: template}
 
     @h.monkeypatch(tg, tg.decorators)
     @decorator


[allura] 26/41: [#8349] revert an idiom change that needs to be an exact type() check still

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 83a94abcf387be8b5cc0a147cab80d9da0535d27
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 17:39:35 2020 -0500

    [#8349] revert an idiom change that needs to be an exact type() check still
---
 ForgeTracker/forgetracker/model/ticket.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index 62f85c9..99061c3 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -1176,7 +1176,7 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
     def __json__(self, posts_limit=None, is_export=False):
         parents_json = {}
         for parent in reversed(type(self).mro()):
-            if not isinstance(self, parent) and hasattr(parent, '__json__'):
+            if parent != type(self) and hasattr(parent, '__json__'):
                 kwargs = {}
                 if parent == VersionedArtifact:
                     kwargs['posts_limit'] = posts_limit


[allura] 06/41: [#8349] python-modernize -n -w --no-diffs -f except .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 57c3cf408a1c3691d91a5f31921f1d9f21fafa8f
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 12:35:11 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f except .
---
 Allura/allura/command/show_models.py                | 4 ++--
 Allura/allura/controllers/auth.py                   | 2 +-
 Allura/allura/controllers/repository.py             | 2 +-
 Allura/allura/ext/admin/admin_main.py               | 2 +-
 Allura/allura/lib/import_api.py                     | 2 +-
 Allura/allura/lib/macro.py                          | 2 +-
 Allura/allura/lib/utils.py                          | 2 +-
 Allura/allura/lib/validators.py                     | 4 ++--
 Allura/allura/model/monq_model.py                   | 4 ++--
 Allura/allura/scripts/create_sitemap_files.py       | 2 +-
 Allura/allura/scripts/reindex_projects.py           | 2 +-
 Allura/allura/scripts/reindex_users.py              | 2 +-
 Allura/allura/scripts/trac_export.py                | 2 +-
 Allura/allura/tasks/mail_tasks.py                   | 2 +-
 AlluraTest/alluratest/validation.py                 | 2 +-
 ForgeDiscussion/forgediscussion/controllers/root.py | 4 ++--
 ForgeGit/forgegit/model/git_repo.py                 | 2 +-
 ForgeTracker/forgetracker/import_support.py         | 2 +-
 ForgeTracker/forgetracker/model/ticket.py           | 4 ++--
 scripts/project-import.py                           | 2 +-
 20 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/Allura/allura/command/show_models.py b/Allura/allura/command/show_models.py
index e082f9b..8417bb2 100644
--- a/Allura/allura/command/show_models.py
+++ b/Allura/allura/command/show_models.py
@@ -137,7 +137,7 @@ class ReindexCommand(base.Command):
                     M.artifact_orm_session.clear()
                     try:
                         self._chunked_add_artifacts(ref_ids)
-                    except CompoundError, err:
+                    except CompoundError as err:
                         base.log.exception(
                             'Error indexing artifacts:\n%r', err)
                         base.log.error('%s', err.format_error())
@@ -298,7 +298,7 @@ class EnsureIndexCommand(base.Command):
                         del index_options['unique']
                     collection.ensure_index(idx.index_spec, **index_options)
                     break
-                except DuplicateKeyError, err:
+                except DuplicateKeyError as err:
                     base.log.info('Found dupe key(%s), eliminating dupes', err)
                     self._remove_dupes(collection, idx.index_spec)
         for keys, idx in indexes.iteritems():
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 82ecdf3..002ae8a 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -686,7 +686,7 @@ class PreferencesController(BaseController):
         ap = plugin.AuthenticationProvider.get(request)
         try:
             ap.upload_sshkey(c.user.username, key)
-        except AssertionError, ae:
+        except AssertionError as ae:
             flash('Error uploading key: %s' % ae, 'error')
         flash('Key uploaded')
         redirect('.')
diff --git a/Allura/allura/controllers/repository.py b/Allura/allura/controllers/repository.py
index 7437df3..13fa7af 100644
--- a/Allura/allura/controllers/repository.py
+++ b/Allura/allura/controllers/repository.py
@@ -153,7 +153,7 @@ class RepoRootController(BaseController, FeedController):
                     redirect(to_project.url() + mount_point + '/')
                 except exc.HTTPRedirection:
                     raise
-                except Exception, ex:
+                except Exception as ex:
                     flash(str(ex), 'error')
                     redirect(request.referer or '/')
 
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index 622aafd..e593bba 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -641,7 +641,7 @@ class ProjectAdminController(BaseController):
                     if callable(new_url):  # subprojects have a method instead of property
                         new_url = new_url()
                     redirect(new_url)
-        except forge_exc.ForgeError, exc:
+        except forge_exc.ForgeError as exc:
             flash('%s: %s' % (exc.__class__.__name__, exc.args[0]),
                   'error')
         if request.referer is not None and tool is not None and 'delete' in tool[0] and \
diff --git a/Allura/allura/lib/import_api.py b/Allura/allura/lib/import_api.py
index 71080ba..95e214a 100644
--- a/Allura/allura/lib/import_api.py
+++ b/Allura/allura/lib/import_api.py
@@ -52,7 +52,7 @@ class AlluraImportApiClient(object):
                 result = urllib2.urlopen(url, urllib.urlencode(params))
                 resp = result.read()
                 return json.loads(resp)
-            except urllib2.HTTPError, e:
+            except urllib2.HTTPError as e:
                 e.msg += ' ({0})'.format(url)
                 if self.verbose:
                     error_content = e.read()
diff --git a/Allura/allura/lib/macro.py b/Allura/allura/lib/macro.py
index 911be84..b0c7f46 100644
--- a/Allura/allura/lib/macro.py
+++ b/Allura/allura/lib/macro.py
@@ -83,7 +83,7 @@ class parse(object):
                          exc_info=True)
                 msg = cgi.escape('[[%s]] (%s)' % (s, repr(ex)))
                 return '\n<div class="error"><pre><code>%s</code></pre></div>' % msg
-        except Exception, ex:
+        except Exception as ex:
             raise
             return '[[Error parsing %s: %s]]' % (s, ex)
 
diff --git a/Allura/allura/lib/utils.py b/Allura/allura/lib/utils.py
index 45bee24..cedc50d 100644
--- a/Allura/allura/lib/utils.py
+++ b/Allura/allura/lib/utils.py
@@ -66,7 +66,7 @@ MARKDOWN_EXTENSIONS = ['.markdown', '.mdown', '.mkdn', '.mkd', '.md']
 def permanent_redirect(url):
     try:
         tg.redirect(url)
-    except exc.HTTPFound, err:
+    except exc.HTTPFound as err:
         raise exc.HTTPMovedPermanently(location=err.location)
 
 
diff --git a/Allura/allura/lib/validators.py b/Allura/allura/lib/validators.py
index 2041dcb..c92535b 100644
--- a/Allura/allura/lib/validators.py
+++ b/Allura/allura/lib/validators.py
@@ -250,7 +250,7 @@ class JsonValidator(fev.FancyValidator):
     def _to_python(self, value, state):
         try:
             json.loads(value)
-        except ValueError, e:
+        except ValueError as e:
             raise fe.Invalid('Invalid JSON: ' + str(e), value, state)
         return value
 
@@ -265,7 +265,7 @@ class JsonConverter(fev.FancyValidator):
     def _to_python(self, value, state):
         try:
             obj = json.loads(value)
-        except ValueError, e:
+        except ValueError as e:
             raise fe.Invalid('Invalid JSON: ' + str(e), value, state)
         if not isinstance(obj, dict):
             raise fe.Invalid('Not a dict (JSON object)', value, state)
diff --git a/Allura/allura/model/monq_model.py b/Allura/allura/model/monq_model.py
index ded8229..b715f33 100644
--- a/Allura/allura/model/monq_model.py
+++ b/Allura/allura/model/monq_model.py
@@ -205,7 +205,7 @@ class MonQTask(MappedClass):
                     sort=cls.sort)
                 if obj is not None:
                     return obj
-            except pymongo.errors.OperationFailure, exc:
+            except pymongo.errors.OperationFailure as exc:
                 if 'No matching object found' not in exc.args[0]:
                     raise
             if waitfunc is None:
@@ -266,7 +266,7 @@ class MonQTask(MappedClass):
                 self.result = func(*self.args, **self.kwargs)
             self.state = 'complete'
             return self.result
-        except Exception, exc:
+        except Exception as exc:
             if asbool(config.get('monq.raise_errors')):
                 raise
             else:
diff --git a/Allura/allura/scripts/create_sitemap_files.py b/Allura/allura/scripts/create_sitemap_files.py
index 2bdbb86..f20645a 100644
--- a/Allura/allura/scripts/create_sitemap_files.py
+++ b/Allura/allura/scripts/create_sitemap_files.py
@@ -117,7 +117,7 @@ class CreateSitemapFiles(ScriptTask):
                         locs.append({'url': url,
                                      'date': p.last_updated.strftime("%Y-%m-%d")})
 
-                except Exception, e:
+                except Exception as e:
                     print "Error creating sitemap for project '%s': %s" %\
                         (p.shortname, e)
                 creds.clear()
diff --git a/Allura/allura/scripts/reindex_projects.py b/Allura/allura/scripts/reindex_projects.py
index f14b973..0e65538 100644
--- a/Allura/allura/scripts/reindex_projects.py
+++ b/Allura/allura/scripts/reindex_projects.py
@@ -62,7 +62,7 @@ class ReindexProjects(ScriptTask):
                         cls._post_add_projects(chunk)
                     else:
                         add_projects(chunk)
-            except CompoundError, err:
+            except CompoundError as err:
                 log.exception('Error indexing projects:\n%r', err)
                 log.error('%s', err.format_error())
             M.main_orm_session.flush()
diff --git a/Allura/allura/scripts/reindex_users.py b/Allura/allura/scripts/reindex_users.py
index 427cd09..ccd40c0 100644
--- a/Allura/allura/scripts/reindex_users.py
+++ b/Allura/allura/scripts/reindex_users.py
@@ -48,7 +48,7 @@ class ReindexUsers(ScriptTask):
                         cls._post_add_users(chunk)
                     else:
                         add_users(chunk)
-            except CompoundError, err:
+            except CompoundError as err:
                 log.exception('Error indexing users:\n%r', err)
                 log.error('%s', err.format_error())
             M.main_orm_session.flush()
diff --git a/Allura/allura/scripts/trac_export.py b/Allura/allura/scripts/trac_export.py
index 19ec460..7ad2277 100644
--- a/Allura/allura/scripts/trac_export.py
+++ b/Allura/allura/scripts/trac_export.py
@@ -252,7 +252,7 @@ class TracExport(object):
         url = self.full_url(self.QUERY_BY_PAGE_URL % self.page, 'csv')
         try:
             f = self.csvopen(url)
-        except urllib2.HTTPError, e:
+        except urllib2.HTTPError as e:
             if 'emulated' in e.msg:
                 body = e.fp.read()
                 if 'beyond the number of pages in the query' in six.ensure_text(body):
diff --git a/Allura/allura/tasks/mail_tasks.py b/Allura/allura/tasks/mail_tasks.py
index eaa730e..f8f1cc0 100644
--- a/Allura/allura/tasks/mail_tasks.py
+++ b/Allura/allura/tasks/mail_tasks.py
@@ -101,7 +101,7 @@ def route_email(
                                 c.app.handle_message(userpart, msg)
                         else:
                             c.app.handle_message(userpart, msg)
-            except exc.MailError, e:
+            except exc.MailError as e:
                 log.error('Error routing email to %s: %s', addr, e)
             except:
                 log.exception('Error routing mail to %s', addr)
diff --git a/AlluraTest/alluratest/validation.py b/AlluraTest/alluratest/validation.py
index e7bcd85..a6bf827 100644
--- a/AlluraTest/alluratest/validation.py
+++ b/AlluraTest/alluratest/validation.py
@@ -117,7 +117,7 @@ def validate_json(json_or_response):
 
     try:
         obj = json.loads(j)
-    except Exception, e:
+    except Exception as e:
         ok_(False, "Couldn't validate JSON: " + str(e) + ':' + j[:100] + '...')
 
     return obj
diff --git a/ForgeDiscussion/forgediscussion/controllers/root.py b/ForgeDiscussion/forgediscussion/controllers/root.py
index 0b7d940..9102ebb 100644
--- a/ForgeDiscussion/forgediscussion/controllers/root.py
+++ b/ForgeDiscussion/forgediscussion/controllers/root.py
@@ -323,7 +323,7 @@ class RootRestController(BaseController, AppRestControllerMixin):
             warnings, doc = import_support.validate_import(
                 doc, username_mapping)
             return dict(warnings=warnings, errors=[])
-        except Exception, e:
+        except Exception as e:
             raise
             log.exception(e)
             return dict(status=False, errors=[repr(e)])
@@ -344,7 +344,7 @@ class RootRestController(BaseController, AppRestControllerMixin):
             warnings = import_support.perform_import(
                 doc, username_mapping, default_username, create_users)
             return dict(warnings=warnings, errors=[])
-        except Exception, e:
+        except Exception as e:
             raise
             log.exception(e)
             return dict(status=False, errors=[str(e)])
diff --git a/ForgeGit/forgegit/model/git_repo.py b/ForgeGit/forgegit/model/git_repo.py
index 26f8bae..171c69a 100644
--- a/ForgeGit/forgegit/model/git_repo.py
+++ b/ForgeGit/forgegit/model/git_repo.py
@@ -166,7 +166,7 @@ class GitImplementation(M.RepositoryImplementation):
             _git = git.Repo(self._repo.full_fs_path, odbt=git.GitCmdObjectDB)
             _git.git = GitLibCmdWrapper(_git.git)
             return _git
-        except (git.exc.NoSuchPathError, git.exc.InvalidGitRepositoryError), err:
+        except (git.exc.NoSuchPathError, git.exc.InvalidGitRepositoryError) as err:
             log.error('Problem looking up repo: %r', err)
             return None
 
diff --git a/ForgeTracker/forgetracker/import_support.py b/ForgeTracker/forgetracker/import_support.py
index c0f5f89..fe789a5 100644
--- a/ForgeTracker/forgetracker/import_support.py
+++ b/ForgeTracker/forgetracker/import_support.py
@@ -366,7 +366,7 @@ option user_map to avoid losing username information. Unknown users: %s''' % unk
             for a_entry in attachments:
                 try:
                     self.make_attachment(a['id'], t._id, a_entry)
-                except Exception, e:
+                except Exception as e:
                     self.warnings.append(
                         'Could not import attachment, skipped: %s' % e)
             log.info('Imported ticket: %d', t.ticket_num)
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index fd4a412..a98ee03 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -685,7 +685,7 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
             try:
                 session(ticket).flush(ticket)
                 return ticket
-            except OperationFailure, err:
+            except OperationFailure as err:
                 if 'duplicate' in err.args[0]:
                     log.warning('Try to create duplicate ticket %s',
                                 ticket.url())
@@ -1096,7 +1096,7 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
             try:
                 session(self).flush(self)
                 break
-            except OperationFailure, err:
+            except OperationFailure as err:
                 if 'duplicate' in err.args[0]:
                     log.warning(
                         'Try to create duplicate ticket %s when moving from %s' %
diff --git a/scripts/project-import.py b/scripts/project-import.py
index eedbf1d..c210989 100644
--- a/scripts/project-import.py
+++ b/scripts/project-import.py
@@ -232,7 +232,7 @@ def create_project(p, nbhd, options):
                                             p.admin,
                                             project_name=p.name.name,
                                             private_project=p.private)
-        except Exception, e:
+        except Exception as e:
             log.exception('[%s] %s' % (worker_name, str(e)))
             return 0
     else:


[allura] 37/41: [#8349] python-modernize -n -w --no-diffs -f reduce .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit f5ec377e82ca3f60bd61f0b3af0dc7e1c38bd3c2
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 17:00:54 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f reduce .
---
 Allura/allura/lib/widgets/forms.py | 1 +
 Allura/allura/model/stats.py       | 1 +
 2 files changed, 2 insertions(+)

diff --git a/Allura/allura/lib/widgets/forms.py b/Allura/allura/lib/widgets/forms.py
index 0c911c0..a528269 100644
--- a/Allura/allura/lib/widgets/forms.py
+++ b/Allura/allura/lib/widgets/forms.py
@@ -38,6 +38,7 @@ from allura.lib import exceptions as forge_exc
 from allura import model as M
 import six
 from six.moves import filter
+from functools import reduce
 
 
 log = logging.getLogger(__name__)
diff --git a/Allura/allura/model/stats.py b/Allura/allura/model/stats.py
index baa24ec..762572f 100644
--- a/Allura/allura/model/stats.py
+++ b/Allura/allura/model/stats.py
@@ -30,6 +30,7 @@ import difflib
 
 from allura.model.session import main_orm_session
 from six.moves import range
+from functools import reduce
 
 
 class Stats(MappedClass):


[allura] 35/41: [#8349] io.open and 'rb' tweaks after 'file' fixer

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 4bac431ad05d407ab87b6dcbb397845ddc5b2210
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 15:40:04 2020 -0500

    [#8349] io.open and 'rb' tweaks after 'file' fixer
---
 Allura/allura/tests/functional/test_admin.py            |  7 ++++---
 Allura/allura/tests/functional/test_home.py             |  3 ++-
 Allura/allura/tests/functional/test_neighborhood.py     |  5 +++--
 ForgeTracker/forgetracker/tests/functional/test_root.py | 17 +++++++++--------
 ForgeWiki/forgewiki/tests/functional/test_rest.py       |  3 ++-
 ForgeWiki/forgewiki/tests/functional/test_root.py       | 11 ++++++-----
 6 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/Allura/allura/tests/functional/test_admin.py b/Allura/allura/tests/functional/test_admin.py
index a55b062..be3a353 100644
--- a/Allura/allura/tests/functional/test_admin.py
+++ b/Allura/allura/tests/functional/test_admin.py
@@ -23,6 +23,7 @@ import allura
 import pkg_resources
 import StringIO
 import logging
+from io import open
 
 import tg
 import PIL
@@ -372,7 +373,7 @@ class TestProjectAdmin(TestController):
         file_name = 'neo-icon-set-454545-256x350.png'
         file_path = os.path.join(
             allura.__path__[0], 'nf', 'allura', 'images', file_name)
-        file_data = open(file_path).read()
+        file_data = open(file_path, 'rb').read()
         upload = ('icon', file_name, file_data)
 
         self.app.get('/admin/')
@@ -396,7 +397,7 @@ class TestProjectAdmin(TestController):
         file_name = 'neo-icon-set-454545-256x350.png'
         file_path = os.path.join(
             allura.__path__[0], 'nf', 'allura', 'images', file_name)
-        file_data = open(file_path).read()
+        file_data = open(file_path, 'rb').read()
         upload = ('screenshot', file_name, file_data)
 
         self.app.get('/admin/')
@@ -436,7 +437,7 @@ class TestProjectAdmin(TestController):
         for file_name in ('admin_24.png', 'admin_32.png'):
             file_path = os.path.join(allura.__path__[0], 'nf', 'allura',
                                      'images', file_name)
-            file_data = open(file_path).read()
+            file_data = open(file_path, 'rb').read()
             upload = ('screenshot', file_name, file_data)
             self.app.post('/admin/add_screenshot', params=dict(
                 caption=file_name),
diff --git a/Allura/allura/tests/functional/test_home.py b/Allura/allura/tests/functional/test_home.py
index 6955a67..1c65816 100644
--- a/Allura/allura/tests/functional/test_home.py
+++ b/Allura/allura/tests/functional/test_home.py
@@ -20,6 +20,7 @@ from __future__ import absolute_import
 import json
 import re
 import os
+from io import open
 
 from tg import tmpl_context as c
 from nose.tools import assert_equal, assert_not_in, assert_in
@@ -157,7 +158,7 @@ class TestProjectHome(TestController):
     def test_user_icon(self):
         file_name = 'neo-icon-set-454545-256x350.png'
         file_path = os.path.join(allura.__path__[0], 'nf', 'allura', 'images', file_name)
-        file_data = open(file_path).read()
+        file_data = open(file_path, 'rb').read()
         upload = ('icon', file_name, file_data)
         with td.audits('update project icon'):
             self.app.post('/u/test-admin/admin/update', params=dict(
diff --git a/Allura/allura/tests/functional/test_neighborhood.py b/Allura/allura/tests/functional/test_neighborhood.py
index 672662c..7ebf528 100644
--- a/Allura/allura/tests/functional/test_neighborhood.py
+++ b/Allura/allura/tests/functional/test_neighborhood.py
@@ -22,6 +22,7 @@ import json
 import os
 from cStringIO import StringIO
 import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
+from io import open
 
 import PIL
 from mock import patch
@@ -266,7 +267,7 @@ class TestNeighborhood(TestController):
         file_name = 'neo-icon-set-454545-256x350.png'
         file_path = os.path.join(
             allura.__path__[0], 'nf', 'allura', 'images', file_name)
-        file_data = open(file_path).read()
+        file_data = open(file_path, 'rb').read()
         upload = ('icon', file_name, file_data)
 
         r = self.app.get('/adobe/_admin/', extra_environ=dict(username=str('root')))
@@ -869,7 +870,7 @@ class TestNeighborhood(TestController):
         file_name = 'adobe_icon.png'
         file_path = os.path.join(
             allura.__path__[0], 'public', 'nf', 'images', file_name)
-        file_data = open(file_path).read()
+        file_data = open(file_path, 'rb').read()
         upload = ('icon', file_name, file_data)
 
         r = self.app.get('/adobe/_admin/awards',
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index c8e7ae1..3ff8512 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -26,6 +26,7 @@ import json
 import StringIO
 import allura
 import mock
+from io import open
 
 import PIL
 from bs4 import BeautifulSoup
@@ -880,7 +881,7 @@ class TestFunctionalController(TrackerTestController):
 
     def test_new_attachment(self):
         file_name = 'test_root.py'
-        file_data = open(__file__).read()
+        file_data = open(__file__, 'rb').read()
         upload = ('attachment', file_name, file_data)
         self.new_ticket(summary='test new attachment')
         ticket_editor = self.app.post('/bugs/1/update_ticket', {
@@ -895,7 +896,7 @@ class TestFunctionalController(TrackerTestController):
 
     def test_delete_attachment(self):
         file_name = 'test_root.py'
-        file_data = open(__file__).read()
+        file_data = open(__file__, 'rb').read()
         upload = ('attachment', file_name, file_data)
         self.new_ticket(summary='test new attachment')
         ticket_editor = self.app.post('/bugs/1/update_ticket', {
@@ -940,7 +941,7 @@ class TestFunctionalController(TrackerTestController):
 
     def test_new_text_attachment_content(self):
         file_name = 'test_root.py'
-        file_data = open(__file__).read()
+        file_data = open(__file__, 'rb').read()
         upload = ('attachment', file_name, file_data)
         self.new_ticket(summary='test new attachment')
         ticket_editor = self.app.post('/bugs/1/update_ticket', {
@@ -953,7 +954,7 @@ class TestFunctionalController(TrackerTestController):
     def test_two_attachments(self):
         file_name1 = 'test_root1.py'
         file_name2 = 'test_root2.py'
-        file_data = open(__file__).read()
+        file_data = open(__file__, 'rb').read()
         self.new_ticket(summary='test new attachment')
         ticket_editor = self.app.post('/bugs/1/update_ticket', {
             'summary': 'zzz'
@@ -967,7 +968,7 @@ class TestFunctionalController(TrackerTestController):
         file_name = 'neo-icon-set-454545-256x350.png'
         file_path = os.path.join(
             allura.__path__[0], 'nf', 'allura', 'images', file_name)
-        file_data = open(file_path).read()
+        file_data = open(file_path, 'rb').read()
         upload = ('attachment', file_name, file_data)
         self.new_ticket(summary='test new attachment')
         self.app.post('/bugs/1/update_ticket', {
@@ -1672,7 +1673,7 @@ class TestFunctionalController(TrackerTestController):
 
     def test_new_ticket_notification_contains_attachments(self):
         file_name = 'tést_root.py'.encode('utf-8')
-        file_data = open(__file__).read()
+        file_data = open(__file__, 'rb').read()
         upload = ('ticket_form.attachment', file_name, file_data)
         r = self.app.post('/bugs/save_ticket', {
             'ticket_form.summary': 'new ticket with attachment'
@@ -2366,7 +2367,7 @@ class TestFunctionalController(TrackerTestController):
         file_name = 'neo-icon-set-454545-256x350.png'
         file_path = os.path.join(
             allura.__path__[0], 'nf', 'allura', 'images', file_name)
-        file_data = open(file_path).read()
+        file_data = open(file_path, 'rb').read()
         upload = ('attachment', file_name, file_data)
         self.new_ticket(summary='test move attachment')
 
@@ -2466,7 +2467,7 @@ class TestFunctionalController(TrackerTestController):
                      11)
 
         file_name = 'test_root.py'
-        file_data = open(__file__).read()
+        file_data = open(__file__, 'rb').read()
         upload = ('attachment', file_name, file_data)
         r = self.app.post('/bugs/1/update_ticket', {
             'summary': 'test rest attach'
diff --git a/ForgeWiki/forgewiki/tests/functional/test_rest.py b/ForgeWiki/forgewiki/tests/functional/test_rest.py
index 70e08ca..c860e81 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_rest.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_rest.py
@@ -20,6 +20,7 @@
 from __future__ import unicode_literals
 from __future__ import absolute_import
 import json
+from io import open
 
 from nose.tools import assert_equal, assert_in, assert_not_equal
 import tg
@@ -48,7 +49,7 @@ class TestWikiApi(TestRestApiBase):
     def test_get_page(self):
         r = self.app.get('/p/test/wiki/Home/')
         discussion_url = r.html.find('form', id='edit_post')['action'][:-4]
-        content = open(__file__).read()
+        content = open(__file__, 'rb').read()
         self.app.post('/wiki/Home/attach',
                       upload_files=[('file_info', 'test_root.py', content)])
         r = self.app.get('/rest/p/test/wiki/Home/')
diff --git a/ForgeWiki/forgewiki/tests/functional/test_root.py b/ForgeWiki/forgewiki/tests/functional/test_root.py
index b41ae5e..b2a6022 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_root.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_root.py
@@ -24,6 +24,7 @@ import os
 import StringIO
 import allura
 import json
+from io import open
 
 import PIL
 from nose.tools import assert_true, assert_equal, assert_in, assert_not_equal, assert_not_in
@@ -494,7 +495,7 @@ class TestRootController(TestController):
                 'text': 'sometext',
                 'labels': '',
                 })
-        content = open(__file__).read()
+        content = open(__file__, 'rb').read()
         self.app.post(h.urlquote('/wiki/tést/attach'),
                       upload_files=[('file_info', 'test_root.py', content)])
         response = self.app.get(h.urlquote('/wiki/tést/'))
@@ -508,7 +509,7 @@ class TestRootController(TestController):
                 'text': 'sometext',
                 'labels': '',
                 })
-        content = open(__file__).read()
+        content = open(__file__, 'rb').read()
         self.app.post(h.urlquote('/wiki/tést/attach'),
                       upload_files=[('file_info', 'test1.py', content), ('file_info', 'test2.py', content)])
         response = self.app.get(h.urlquote('/wiki/tést/'))
@@ -524,7 +525,7 @@ class TestRootController(TestController):
                 'labels': '',
                 })
         file_name = 'test_root.py'
-        file_data = open(__file__).read()
+        file_data = open(__file__, 'rb').read()
         upload = ('file_info', file_name, file_data)
         self.app.post(h.urlquote('/wiki/tést/attach'), upload_files=[upload])
         page_editor = self.app.get(h.urlquote('/wiki/tést/edit'))
@@ -540,7 +541,7 @@ class TestRootController(TestController):
         file_name = 'neo-icon-set-454545-256x350.png'
         file_path = os.path.join(
             allura.__path__[0], 'nf', 'allura', 'images', file_name)
-        file_data = open(file_path).read()
+        file_data = open(file_path, 'rb').read()
         upload = ('file_info', file_name, file_data)
         self.app.post('/wiki/TEST/attach', upload_files=[upload])
         h.set_context('test', 'wiki', neighborhood='Projects')
@@ -713,7 +714,7 @@ class TestRootController(TestController):
             'labels': '',
             }
         self.app.post('/wiki/TEST/update', params=params)
-        content = open(__file__).read()
+        content = open(__file__, 'rb').read()
         self.app.post('/wiki/TEST/attach',
                       upload_files=[('file_info', 'test_root.py', content)])
         r = self.app.get('/wiki/TEST/')


[allura] 18/41: [#8349] python-modernize -n -w --no-diffs -f raise .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 751b5dd26c6775c3a893cccb68a83c9b3be3190f
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 14:34:40 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f raise .
---
 Allura/allura/app.py                               |  2 +-
 Allura/allura/config/app_cfg.py                    |  2 +-
 Allura/allura/controllers/base.py                  |  2 +-
 Allura/allura/controllers/basetest_project_root.py |  4 ++--
 Allura/allura/controllers/project.py               |  4 ++--
 Allura/allura/controllers/rest.py                  | 10 +++++-----
 Allura/allura/controllers/search.py                |  2 +-
 Allura/allura/controllers/site_admin.py            |  2 +-
 Allura/allura/ext/admin/admin_main.py              |  8 ++++----
 Allura/allura/lib/base.py                          |  2 +-
 Allura/allura/lib/mail_util.py                     |  8 ++++----
 Allura/allura/lib/repository.py                    |  2 +-
 Allura/allura/model/project.py                     |  2 +-
 ForgeTracker/forgetracker/model/ticket.py          |  6 +++---
 ForgeTracker/forgetracker/tracker_main.py          |  2 +-
 15 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/Allura/allura/app.py b/Allura/allura/app.py
index ad7db0c..99ddc4f 100644
--- a/Allura/allura/app.py
+++ b/Allura/allura/app.py
@@ -1058,4 +1058,4 @@ class WebhooksLookup(BaseController, AdminControllerMixin):
         for hook in self.app._webhooks:
             if hook.type == name and hook.controller:
                 return hook.controller(hook, self.app), remainder
-        raise exc.HTTPNotFound, name
+        raise exc.HTTPNotFound(name)
diff --git a/Allura/allura/config/app_cfg.py b/Allura/allura/config/app_cfg.py
index 9e8d023..9ba1639 100644
--- a/Allura/allura/config/app_cfg.py
+++ b/Allura/allura/config/app_cfg.py
@@ -123,7 +123,7 @@ class JinjaEngine(ew.TemplateEngine):
         try:
             return self._environ.get_template(template_name)
         except jinja2.TemplateNotFound:
-            raise ew.errors.TemplateNotFound, '%s not found' % template_name
+            raise ew.errors.TemplateNotFound('%s not found' % template_name)
 
     def parse(self, template_text, filepath=None):
         return self._environ.from_string(template_text)
diff --git a/Allura/allura/controllers/base.py b/Allura/allura/controllers/base.py
index b47d4c0..a61beab 100644
--- a/Allura/allura/controllers/base.py
+++ b/Allura/allura/controllers/base.py
@@ -35,7 +35,7 @@ class BaseController(object):
     def _lookup(self, name=None, *remainder):
         """Provide explicit default lookup to avoid dispatching backtracking
         and possible loops."""
-        raise exc.HTTPNotFound, name
+        raise exc.HTTPNotFound(name)
 
     def rate_limit(self, artifact_class, message, redir='..'):
         if artifact_class.is_limit_exceeded(c.app.config, user=c.user):
diff --git a/Allura/allura/controllers/basetest_project_root.py b/Allura/allura/controllers/basetest_project_root.py
index 5364cb4..459c95e 100644
--- a/Allura/allura/controllers/basetest_project_root.py
+++ b/Allura/allura/controllers/basetest_project_root.py
@@ -104,10 +104,10 @@ class BasetestProjectRootController(WsgiDispatchController, ProjectController):
             try:
                 c.project.install_app(ep_name, name)
             except KeyError:
-                raise exc.HTTPNotFound, name
+                raise exc.HTTPNotFound(name)
             app = c.project.app_instance(name)
             if app is None:
-                raise exc.HTTPNotFound, name
+                raise exc.HTTPNotFound(name)
         c.app = app
         return app.root, remainder
 
diff --git a/Allura/allura/controllers/project.py b/Allura/allura/controllers/project.py
index d061315..7e322f1 100644
--- a/Allura/allura/controllers/project.py
+++ b/Allura/allura/controllers/project.py
@@ -346,7 +346,7 @@ class ProjectController(FeedController):
 
         if c.project.deleted:
             if c.user not in c.project.admins():
-                raise exc.HTTPNotFound, name
+                raise exc.HTTPNotFound(name)
         app = c.project.app_instance(name)
 
         if app:
@@ -360,7 +360,7 @@ class ProjectController(FeedController):
             c.project = subproject
             c.app = None
             return ProjectController(), remainder
-        raise exc.HTTPNotFound, name
+        raise exc.HTTPNotFound(name)
 
     @expose('jinja:allura:templates/members.html')
     @with_trailing_slash
diff --git a/Allura/allura/controllers/rest.py b/Allura/allura/controllers/rest.py
index f488595..4603878 100644
--- a/Allura/allura/controllers/rest.py
+++ b/Allura/allura/controllers/rest.py
@@ -112,7 +112,7 @@ class RestController(object):
             c.user = c.api_token.user
         neighborhood = M.Neighborhood.query.get(url_prefix='/' + name + '/')
         if not neighborhood:
-            raise exc.HTTPNotFound, name
+            raise exc.HTTPNotFound(name)
         return NeighborhoodRestController(neighborhood), remainder
 
 
@@ -345,9 +345,9 @@ def nbhd_lookup_first_path(nbhd, name, current_user, remainder, api=False):
             log.info('Configuring %s database for access to %r', pname, remainder)
             project.configure_project(is_user_project=True)
         else:
-            raise exc.HTTPNotFound, pname
+            raise exc.HTTPNotFound(pname)
     if project is None or (project.deleted and not has_access(project, 'update')()):
-        raise exc.HTTPNotFound, pname
+        raise exc.HTTPNotFound(pname)
     return project, remainder
 
 
@@ -384,10 +384,10 @@ class ProjectRestController(object):
             return ProjectRestController(), remainder
         app = c.project.app_instance(name)
         if app is None:
-            raise exc.HTTPNotFound, name
+            raise exc.HTTPNotFound(name)
         c.app = app
         if app.api_root is None:
-            raise exc.HTTPNotFound, name
+            raise exc.HTTPNotFound(name)
         return app.api_root, remainder
 
     @expose('json:')
diff --git a/Allura/allura/controllers/search.py b/Allura/allura/controllers/search.py
index 3e55708..cf6a6d9 100644
--- a/Allura/allura/controllers/search.py
+++ b/Allura/allura/controllers/search.py
@@ -68,7 +68,7 @@ class ProjectBrowseController(BaseController):
             self.category = M.ProjectCategory.query.find(
                 dict(name=category_name, parent_id=parent_id)).first()
             if not self.category:
-                raise exc.HTTPNotFound, request.path
+                raise exc.HTTPNotFound(request.path)
         else:
             self.category = None
 
diff --git a/Allura/allura/controllers/site_admin.py b/Allura/allura/controllers/site_admin.py
index 75922a4..f703a11 100644
--- a/Allura/allura/controllers/site_admin.py
+++ b/Allura/allura/controllers/site_admin.py
@@ -84,7 +84,7 @@ class SiteAdminController(object):
             controller = admin_extension().controllers.get(name)
             if controller:
                 return controller(), remainder
-        raise HTTPNotFound, name
+        raise HTTPNotFound(name)
 
     def sidebar_menu(self):
         base_url = '/nf/admin/'
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index a9fedc4..cd14c06 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -197,7 +197,7 @@ class AdminExtensionLookup(object):
             controller = admin_extension().project_admin_controllers.get(name)
             if controller:
                 return controller(), remainder
-        raise exc.HTTPNotFound, name
+        raise exc.HTTPNotFound(name)
 
 
 class ProjectAdminController(BaseController):
@@ -301,7 +301,7 @@ class ProjectAdminController(BaseController):
     def _lookup(self, name, *remainder):
         app = c.project.app_instance(name)
         if app is None:
-            raise exc.HTTPNotFound, name
+            raise exc.HTTPNotFound(name)
         return app.admin, remainder
 
     @without_trailing_slash
@@ -956,11 +956,11 @@ class ProjectAdminRestController(BaseController):
     @expose()
     def _lookup(self, *args):
         if len(args) == 0:
-            raise exc.HTTPNotFound, args
+            raise exc.HTTPNotFound(args)
         name, remainder = args[0], args[1:]
         app = c.project.app_instance(name)
         if app is None or app.admin_api_root is None:
-            raise exc.HTTPNotFound, name
+            raise exc.HTTPNotFound(name)
         return app.admin_api_root, remainder
 
 
diff --git a/Allura/allura/lib/base.py b/Allura/allura/lib/base.py
index de91eb1..dc430c3 100644
--- a/Allura/allura/lib/base.py
+++ b/Allura/allura/lib/base.py
@@ -37,7 +37,7 @@ class WsgiDispatchController(TGController):
 
     def _setup_request(self):
         '''Responsible for setting all the values we need to be set on tg.tmpl_context'''
-        raise NotImplementedError, '_setup_request'
+        raise NotImplementedError('_setup_request')
 
     def _perform_call(self, context):
         self._setup_request()
diff --git a/Allura/allura/lib/mail_util.py b/Allura/allura/lib/mail_util.py
index eb89c15..e686502 100644
--- a/Allura/allura/lib/mail_util.py
+++ b/Allura/allura/lib/mail_util.py
@@ -110,17 +110,17 @@ def parse_address(addr):
             domain = domain[:-len(suffix)]
             break
     else:
-        raise exc.AddressException, 'Unknown domain: ' + domain
+        raise exc.AddressException('Unknown domain: ' + domain)
     path = '/'.join(reversed(domain.split('.')))
     project, mount_point = h.find_project('/' + path)
     if project is None:
-        raise exc.AddressException, 'Unknown project: ' + domain
+        raise exc.AddressException('Unknown project: ' + domain)
     if len(mount_point) != 1:
-        raise exc.AddressException, 'Unknown tool: ' + domain
+        raise exc.AddressException('Unknown tool: ' + domain)
     with h.push_config(c, project=project):
         app = project.app_instance(mount_point[0])
         if not app:
-            raise exc.AddressException, 'Unknown tool: ' + domain
+            raise exc.AddressException('Unknown tool: ' + domain)
     return userpart, project, app
 
 
diff --git a/Allura/allura/lib/repository.py b/Allura/allura/lib/repository.py
index 2ad3a5a..af88d9b 100644
--- a/Allura/allura/lib/repository.py
+++ b/Allura/allura/lib/repository.py
@@ -351,4 +351,4 @@ class RestWebhooksLookup(BaseController):
         for hook in self.app._webhooks:
             if hook.type == name and hook.api_controller:
                 return hook.api_controller(hook, self.app), remainder
-        raise exc.HTTPNotFound, name
+        raise exc.HTTPNotFound(name)
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index 4bd97ad..23fc27b 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -877,7 +877,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
             provider.shortname_validator.to_python(
                 name, check_allowed=False, neighborhood=self.neighborhood)
         except exceptions.Invalid:
-            raise exceptions.ToolError, 'Mount point "%s" is invalid' % name
+            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):
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index 17e890e..99061c3 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -829,11 +829,11 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
                 fld = f
                 break
         if not fld:
-            raise KeyError, 'Custom field "%s" does not exist.' % custom_user_field_name
+            raise KeyError('Custom field "%s" does not exist.' % custom_user_field_name)
         if fld.type != 'user':
-            raise TypeError, 'Custom field "%s" is of type "%s"; expected ' \
+            raise TypeError('Custom field "%s" is of type "%s"; expected ' \
                              'type "user".' % (
-                                 custom_user_field_name, fld.type)
+                                 custom_user_field_name, fld.type))
         username = self.custom_fields.get(custom_user_field_name)
         if not username:
             return None
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index c39b54f..2873051 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -1379,7 +1379,7 @@ class TicketController(BaseController, FeedController):
                         subscribed=subscribed, voting_enabled=voting_enabled,
                         page=page, limit=limit, count=post_count)
         else:
-            raise exc.HTTPNotFound, 'Ticket #%s does not exist.' % self.ticket_num
+            raise exc.HTTPNotFound('Ticket #%s does not exist.' % self.ticket_num)
 
     def get_feed(self, project, app, user):
         """Return a :class:`allura.controllers.feed.FeedArgs` object describing


[allura] 08/41: [#8349] python-modernize -n -w --no-diffs -f import .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 6cb68ca9d65b89014574d444b3927c89e72dd595
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 12:43:16 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f import .
---
 Allura/allura/__init__.py                                 |  1 +
 Allura/allura/app.py                                      |  3 ++-
 Allura/allura/command/__init__.py                         | 15 ++++++++-------
 Allura/allura/command/base.py                             |  1 +
 Allura/allura/command/create_neighborhood.py              |  1 +
 Allura/allura/command/create_trove_categories.py          |  1 +
 Allura/allura/command/reclone_repo.py                     |  1 +
 Allura/allura/command/script.py                           |  1 +
 Allura/allura/command/set_neighborhood_features.py        |  1 +
 Allura/allura/command/show_models.py                      |  1 +
 Allura/allura/command/smtp_server.py                      |  1 +
 Allura/allura/command/taskd.py                            |  3 ++-
 Allura/allura/command/taskd_cleanup.py                    |  3 ++-
 Allura/allura/config/app_cfg.py                           |  1 +
 Allura/allura/config/environment.py                       |  1 +
 Allura/allura/config/middleware.py                        |  1 +
 Allura/allura/config/resources.py                         |  1 +
 Allura/allura/controllers/attachments.py                  |  1 +
 Allura/allura/controllers/auth.py                         |  1 +
 Allura/allura/controllers/base.py                         |  1 +
 Allura/allura/controllers/basetest_project_root.py        |  1 +
 Allura/allura/controllers/discuss.py                      |  3 ++-
 Allura/allura/controllers/error.py                        |  1 +
 Allura/allura/controllers/feed.py                         |  1 +
 Allura/allura/controllers/project.py                      |  1 +
 Allura/allura/controllers/repository.py                   |  1 +
 Allura/allura/controllers/rest.py                         |  1 +
 Allura/allura/controllers/root.py                         |  1 +
 Allura/allura/controllers/search.py                       |  1 +
 Allura/allura/controllers/site_admin.py                   |  1 +
 Allura/allura/controllers/static.py                       |  1 +
 Allura/allura/controllers/task.py                         |  1 +
 Allura/allura/controllers/trovecategories.py              |  1 +
 Allura/allura/ext/admin/admin_main.py                     |  1 +
 Allura/allura/ext/admin/widgets.py                        |  1 +
 Allura/allura/ext/personal_dashboard/dashboard_main.py    |  1 +
 Allura/allura/ext/project_home/project_main.py            |  1 +
 Allura/allura/ext/search/search_main.py                   |  1 +
 Allura/allura/ext/user_profile/user_main.py               |  1 +
 Allura/allura/lib/AsciiDammit.py                          |  1 +
 Allura/allura/lib/app_globals.py                          |  1 +
 Allura/allura/lib/base.py                                 |  1 +
 Allura/allura/lib/custom_middleware.py                    |  1 +
 Allura/allura/lib/decorators.py                           |  1 +
 Allura/allura/lib/diff.py                                 |  1 +
 Allura/allura/lib/exceptions.py                           |  1 +
 Allura/allura/lib/gravatar.py                             |  1 +
 Allura/allura/lib/helpers.py                              |  1 +
 Allura/allura/lib/import_api.py                           |  1 +
 Allura/allura/lib/macro.py                                |  1 +
 Allura/allura/lib/mail_util.py                            |  1 +
 Allura/allura/lib/markdown_extensions.py                  |  1 +
 Allura/allura/lib/multifactor.py                          |  1 +
 Allura/allura/lib/package_path_loader.py                  |  1 +
 Allura/allura/lib/patches.py                              |  1 +
 Allura/allura/lib/phone/__init__.py                       |  1 +
 Allura/allura/lib/phone/nexmo.py                          |  1 +
 Allura/allura/lib/plugin.py                               |  1 +
 Allura/allura/lib/repository.py                           |  1 +
 Allura/allura/lib/search.py                               |  1 +
 Allura/allura/lib/solr.py                                 |  1 +
 Allura/allura/lib/spam/__init__.py                        |  1 +
 Allura/allura/lib/spam/akismetfilter.py                   |  1 +
 Allura/allura/lib/spam/stopforumspamfilter.py             |  1 +
 Allura/allura/lib/utils.py                                |  1 +
 Allura/allura/lib/validators.py                           |  1 +
 Allura/allura/lib/widgets/analytics.py                    |  1 +
 Allura/allura/lib/widgets/auth_widgets.py                 |  1 +
 Allura/allura/lib/widgets/discuss.py                      |  1 +
 Allura/allura/lib/widgets/form_fields.py                  |  1 +
 Allura/allura/lib/widgets/forms.py                        |  1 +
 Allura/allura/lib/widgets/macros.py                       |  1 +
 Allura/allura/lib/widgets/oauth_widgets.py                |  1 +
 Allura/allura/lib/widgets/project_list.py                 |  1 +
 Allura/allura/lib/widgets/repo.py                         |  1 +
 Allura/allura/lib/widgets/search.py                       |  1 +
 Allura/allura/lib/widgets/subscriptions.py                |  1 +
 Allura/allura/lib/widgets/user_profile.py                 |  1 +
 Allura/allura/lib/widgets/vote.py                         |  1 +
 Allura/allura/model/__init__.py                           |  1 +
 Allura/allura/model/artifact.py                           |  3 ++-
 Allura/allura/model/attachments.py                        |  1 +
 Allura/allura/model/auth.py                               |  1 +
 Allura/allura/model/discuss.py                            |  1 +
 Allura/allura/model/filesystem.py                         |  1 +
 Allura/allura/model/index.py                              |  1 +
 Allura/allura/model/monq_model.py                         |  1 +
 Allura/allura/model/multifactor.py                        |  1 +
 Allura/allura/model/neighborhood.py                       |  1 +
 Allura/allura/model/notification.py                       |  1 +
 Allura/allura/model/oauth.py                              |  1 +
 Allura/allura/model/project.py                            |  3 ++-
 Allura/allura/model/repo_refresh.py                       |  1 +
 Allura/allura/model/repository.py                         |  1 +
 Allura/allura/model/session.py                            |  1 +
 Allura/allura/model/stats.py                              |  1 +
 Allura/allura/model/timeline.py                           |  1 +
 Allura/allura/model/types.py                              |  1 +
 Allura/allura/model/webhook.py                            |  1 +
 Allura/allura/scripts/__init__.py                         |  3 ++-
 Allura/allura/scripts/create_sitemap_files.py             |  1 +
 Allura/allura/scripts/delete_projects.py                  |  1 +
 Allura/allura/scripts/disable_users.py                    |  1 +
 Allura/allura/scripts/refresh_last_commits.py             |  1 +
 Allura/allura/scripts/refreshrepo.py                      |  1 +
 Allura/allura/scripts/reindex_projects.py                 |  1 +
 Allura/allura/scripts/reindex_users.py                    |  1 +
 Allura/allura/scripts/scripttask.py                       |  1 +
 Allura/allura/scripts/trac_export.py                      |  1 +
 Allura/allura/tasks/activity_tasks.py                     |  1 +
 Allura/allura/tasks/admin_tasks.py                        |  1 +
 Allura/allura/tasks/event_tasks.py                        |  1 +
 Allura/allura/tasks/export_tasks.py                       |  1 +
 Allura/allura/tasks/index_tasks.py                        |  1 +
 Allura/allura/tasks/mail_tasks.py                         |  1 +
 Allura/allura/tasks/notification_tasks.py                 |  1 +
 Allura/allura/tasks/repo_tasks.py                         |  1 +
 Allura/allura/tests/__init__.py                           |  1 +
 Allura/allura/tests/decorators.py                         |  1 +
 Allura/allura/tests/functional/test_admin.py              |  1 +
 Allura/allura/tests/functional/test_auth.py               |  1 +
 Allura/allura/tests/functional/test_discuss.py            |  1 +
 Allura/allura/tests/functional/test_feeds.py              |  1 +
 Allura/allura/tests/functional/test_gravatar.py           |  1 +
 Allura/allura/tests/functional/test_home.py               |  1 +
 Allura/allura/tests/functional/test_nav.py                |  1 +
 Allura/allura/tests/functional/test_neighborhood.py       |  1 +
 Allura/allura/tests/functional/test_personal_dashboard.py |  1 +
 Allura/allura/tests/functional/test_rest.py               |  1 +
 Allura/allura/tests/functional/test_root.py               |  1 +
 Allura/allura/tests/functional/test_search.py             |  1 +
 Allura/allura/tests/functional/test_site_admin.py         |  1 +
 Allura/allura/tests/functional/test_static.py             |  1 +
 Allura/allura/tests/functional/test_subscriber.py         |  1 +
 Allura/allura/tests/functional/test_tool_list.py          |  1 +
 Allura/allura/tests/functional/test_trovecategory.py      |  1 +
 Allura/allura/tests/functional/test_user_profile.py       |  1 +
 Allura/allura/tests/model/test_artifact.py                |  1 +
 Allura/allura/tests/model/test_auth.py                    |  1 +
 Allura/allura/tests/model/test_discussion.py              |  1 +
 Allura/allura/tests/model/test_filesystem.py              |  1 +
 Allura/allura/tests/model/test_monq.py                    |  1 +
 Allura/allura/tests/model/test_neighborhood.py            |  1 +
 Allura/allura/tests/model/test_notification.py            |  1 +
 Allura/allura/tests/model/test_oauth.py                   |  1 +
 Allura/allura/tests/model/test_project.py                 |  1 +
 Allura/allura/tests/model/test_repo.py                    |  1 +
 Allura/allura/tests/model/test_timeline.py                |  1 +
 Allura/allura/tests/scripts/test_create_sitemap_files.py  |  1 +
 Allura/allura/tests/scripts/test_delete_projects.py       |  1 +
 Allura/allura/tests/scripts/test_reindexes.py             |  1 +
 Allura/allura/tests/templates/jinja_master/test_lib.py    |  1 +
 Allura/allura/tests/test_app.py                           |  1 +
 Allura/allura/tests/test_commands.py                      |  1 +
 Allura/allura/tests/test_decorators.py                    |  1 +
 Allura/allura/tests/test_diff.py                          |  1 +
 Allura/allura/tests/test_dispatch.py                      |  1 +
 Allura/allura/tests/test_globals.py                       |  1 +
 Allura/allura/tests/test_helpers.py                       |  1 +
 Allura/allura/tests/test_mail_util.py                     |  1 +
 Allura/allura/tests/test_markdown.py                      |  1 +
 Allura/allura/tests/test_middlewares.py                   |  1 +
 Allura/allura/tests/test_multifactor.py                   |  1 +
 Allura/allura/tests/test_patches.py                       |  1 +
 Allura/allura/tests/test_plugin.py                        |  1 +
 Allura/allura/tests/test_scripttask.py                    |  1 +
 Allura/allura/tests/test_security.py                      |  1 +
 Allura/allura/tests/test_tasks.py                         |  1 +
 Allura/allura/tests/test_utils.py                         |  1 +
 Allura/allura/tests/test_validators.py                    |  1 +
 Allura/allura/tests/test_webhooks.py                      |  1 +
 Allura/allura/tests/tscript.py                            |  1 +
 Allura/allura/tests/unit/__init__.py                      |  1 +
 Allura/allura/tests/unit/controllers/test_auth.py         |  1 +
 .../controllers/test_discussion_moderation_controller.py  |  1 +
 .../allura/tests/unit/controllers/test_dispatch_index.py  |  1 +
 Allura/allura/tests/unit/factories.py                     |  1 +
 Allura/allura/tests/unit/patches.py                       |  1 +
 Allura/allura/tests/unit/phone/test_nexmo.py              |  1 +
 Allura/allura/tests/unit/phone/test_phone_service.py      |  1 +
 Allura/allura/tests/unit/spam/test_akismet.py             |  1 +
 Allura/allura/tests/unit/spam/test_spam_filter.py         |  1 +
 Allura/allura/tests/unit/spam/test_stopforumspam.py       |  1 +
 Allura/allura/tests/unit/test_app.py                      |  1 +
 Allura/allura/tests/unit/test_artifact.py                 |  1 +
 Allura/allura/tests/unit/test_discuss.py                  |  1 +
 Allura/allura/tests/unit/test_helpers/test_ago.py         |  1 +
 Allura/allura/tests/unit/test_helpers/test_set_context.py |  1 +
 Allura/allura/tests/unit/test_ldap_auth_provider.py       |  1 +
 Allura/allura/tests/unit/test_mixins.py                   |  1 +
 Allura/allura/tests/unit/test_package_path_loader.py      |  1 +
 Allura/allura/tests/unit/test_post_model.py               |  1 +
 Allura/allura/tests/unit/test_project.py                  |  1 +
 Allura/allura/tests/unit/test_repo.py                     |  1 +
 Allura/allura/tests/unit/test_session.py                  |  1 +
 Allura/allura/tests/unit/test_sitemapentry.py             |  1 +
 Allura/allura/tests/unit/test_solr.py                     |  1 +
 Allura/allura/webhooks.py                                 |  1 +
 Allura/allura/websetup/__init__.py                        |  5 +++--
 Allura/allura/websetup/bootstrap.py                       |  1 +
 Allura/allura/websetup/schema.py                          |  1 +
 Allura/docs/conf.py                                       |  1 +
 Allura/ldap-setup.py                                      |  1 +
 Allura/ldap-userconfig.py                                 |  1 +
 Allura/setup.py                                           |  1 +
 AlluraTest/alluratest/controller.py                       |  1 +
 AlluraTest/alluratest/pylint_checkers.py                  |  1 +
 AlluraTest/alluratest/smtp_debug.py                       |  1 +
 AlluraTest/alluratest/test_syntax.py                      |  1 +
 AlluraTest/alluratest/validation.py                       |  1 +
 AlluraTest/setup.py                                       |  1 +
 ForgeActivity/forgeactivity/__init__.py                   |  3 ++-
 ForgeActivity/forgeactivity/config/resources.py           |  1 +
 ForgeActivity/forgeactivity/main.py                       |  1 +
 ForgeActivity/forgeactivity/tests/functional/test_rest.py |  1 +
 ForgeActivity/forgeactivity/tests/functional/test_root.py |  1 +
 ForgeActivity/forgeactivity/widgets/follow.py             |  1 +
 ForgeActivity/setup.py                                    |  1 +
 ForgeBlog/forgeblog/command/base.py                       |  1 +
 ForgeBlog/forgeblog/command/rssfeeds.py                   |  3 ++-
 ForgeBlog/forgeblog/main.py                               |  1 +
 ForgeBlog/forgeblog/model/__init__.py                     |  3 ++-
 ForgeBlog/forgeblog/model/blog.py                         |  1 +
 ForgeBlog/forgeblog/tests/functional/test_feeds.py        |  1 +
 ForgeBlog/forgeblog/tests/functional/test_rest.py         |  1 +
 ForgeBlog/forgeblog/tests/functional/test_root.py         |  1 +
 ForgeBlog/forgeblog/tests/test_app.py                     |  1 +
 ForgeBlog/forgeblog/tests/test_commands.py                |  1 +
 ForgeBlog/forgeblog/tests/test_roles.py                   |  1 +
 ForgeBlog/forgeblog/tests/unit/__init__.py                |  1 +
 ForgeBlog/forgeblog/tests/unit/test_blog_post.py          |  1 +
 ForgeBlog/forgeblog/widgets.py                            |  1 +
 ForgeBlog/setup.py                                        |  1 +
 ForgeChat/forgechat/command.py                            |  1 +
 ForgeChat/forgechat/main.py                               |  1 +
 ForgeChat/forgechat/model/__init__.py                     |  3 ++-
 ForgeChat/forgechat/model/chat.py                         |  1 +
 ForgeChat/forgechat/tests/functional/test_root.py         |  1 +
 ForgeChat/setup.py                                        |  1 +
 ForgeDiscussion/forgediscussion/controllers/__init__.py   |  3 ++-
 ForgeDiscussion/forgediscussion/controllers/forum.py      |  1 +
 ForgeDiscussion/forgediscussion/controllers/root.py       |  1 +
 ForgeDiscussion/forgediscussion/forum_main.py             |  3 ++-
 ForgeDiscussion/forgediscussion/import_support.py         |  1 +
 ForgeDiscussion/forgediscussion/model/__init__.py         |  3 ++-
 ForgeDiscussion/forgediscussion/model/forum.py            |  1 +
 ForgeDiscussion/forgediscussion/site_stats.py             |  1 +
 ForgeDiscussion/forgediscussion/tasks.py                  |  1 +
 .../forgediscussion/tests/functional/test_forum.py        |  1 +
 .../forgediscussion/tests/functional/test_forum_admin.py  |  1 +
 .../forgediscussion/tests/functional/test_import.py       |  1 +
 .../forgediscussion/tests/functional/test_rest.py         |  1 +
 ForgeDiscussion/forgediscussion/tests/test_app.py         |  1 +
 ForgeDiscussion/forgediscussion/tests/test_forum_roles.py |  1 +
 ForgeDiscussion/forgediscussion/utils.py                  |  1 +
 ForgeDiscussion/forgediscussion/widgets/__init__.py       |  7 ++++---
 ForgeDiscussion/forgediscussion/widgets/admin.py          |  1 +
 ForgeDiscussion/forgediscussion/widgets/forum_widgets.py  |  1 +
 ForgeDiscussion/setup.py                                  |  1 +
 ForgeFeedback/forgefeedback/feedback_main.py              |  1 +
 ForgeFeedback/forgefeedback/model/__init__.py             |  3 ++-
 ForgeFeedback/forgefeedback/model/feedback.py             |  1 +
 ForgeFeedback/forgefeedback/tests/functional/test_root.py |  1 +
 ForgeFeedback/forgefeedback/tests/test_feedback_roles.py  |  1 +
 ForgeFeedback/forgefeedback/tests/unit/__init__.py        |  1 +
 ForgeFeedback/forgefeedback/tests/unit/test_feedback.py   |  1 +
 .../forgefeedback/tests/unit/test_root_controller.py      |  1 +
 ForgeFeedback/setup.py                                    |  1 +
 ForgeGit/forgegit/controllers.py                          |  1 +
 ForgeGit/forgegit/git_main.py                             |  1 +
 ForgeGit/forgegit/model/__init__.py                       |  3 ++-
 ForgeGit/forgegit/model/git_repo.py                       |  1 +
 ForgeGit/forgegit/tests/__init__.py                       |  1 +
 ForgeGit/forgegit/tests/functional/test_auth.py           |  1 +
 ForgeGit/forgegit/tests/functional/test_controllers.py    |  1 +
 ForgeGit/forgegit/tests/model/test_repository.py          |  1 +
 ForgeGit/forgegit/tests/test_git_app.py                   |  1 +
 ForgeGit/forgegit/tests/test_tasks.py                     |  1 +
 ForgeGit/setup.py                                         |  1 +
 ForgeImporters/forgeimporters/base.py                     |  1 +
 ForgeImporters/forgeimporters/forge/tracker.py            |  1 +
 ForgeImporters/forgeimporters/github/__init__.py          |  1 +
 ForgeImporters/forgeimporters/github/code.py              |  1 +
 ForgeImporters/forgeimporters/github/project.py           |  1 +
 ForgeImporters/forgeimporters/github/tasks.py             |  1 +
 ForgeImporters/forgeimporters/github/tests/test_code.py   |  1 +
 ForgeImporters/forgeimporters/github/tests/test_oauth.py  |  1 +
 .../forgeimporters/github/tests/test_tracker.py           |  1 +
 ForgeImporters/forgeimporters/github/tests/test_utils.py  |  1 +
 ForgeImporters/forgeimporters/github/tests/test_wiki.py   |  1 +
 ForgeImporters/forgeimporters/github/tracker.py           |  1 +
 ForgeImporters/forgeimporters/github/utils.py             |  1 +
 ForgeImporters/forgeimporters/github/wiki.py              |  1 +
 ForgeImporters/forgeimporters/tests/forge/test_tracker.py |  1 +
 .../forgeimporters/tests/github/functional/test_github.py |  1 +
 .../forgeimporters/tests/github/test_extractor.py         |  1 +
 ForgeImporters/forgeimporters/tests/github/test_tasks.py  |  1 +
 .../forgeimporters/tests/github/test_tracker.py           |  1 +
 ForgeImporters/forgeimporters/tests/test_base.py          |  1 +
 ForgeImporters/forgeimporters/trac/__init__.py            |  1 +
 ForgeImporters/forgeimporters/trac/project.py             |  1 +
 .../forgeimporters/trac/tests/functional/test_trac.py     |  1 +
 ForgeImporters/forgeimporters/trac/tests/test_tickets.py  |  1 +
 ForgeImporters/forgeimporters/trac/tickets.py             |  1 +
 ForgeImporters/setup.py                                   |  1 +
 ForgeLink/forgelink/link_main.py                          |  1 +
 ForgeLink/forgelink/tests/functional/test_rest.py         |  1 +
 ForgeLink/forgelink/tests/functional/test_root.py         |  1 +
 ForgeLink/forgelink/tests/test_app.py                     |  1 +
 ForgeLink/setup.py                                        |  1 +
 ForgeSVN/forgesvn/controllers.py                          |  1 +
 ForgeSVN/forgesvn/model/__init__.py                       |  3 ++-
 ForgeSVN/forgesvn/model/svn.py                            |  1 +
 ForgeSVN/forgesvn/svn_main.py                             |  1 +
 ForgeSVN/forgesvn/tests/__init__.py                       |  1 +
 ForgeSVN/forgesvn/tests/functional/test_auth.py           |  1 +
 ForgeSVN/forgesvn/tests/functional/test_controllers.py    |  1 +
 ForgeSVN/forgesvn/tests/model/test_repository.py          |  1 +
 ForgeSVN/forgesvn/tests/model/test_svnimplementation.py   |  1 +
 ForgeSVN/forgesvn/tests/test_svn_app.py                   |  1 +
 ForgeSVN/forgesvn/tests/test_tasks.py                     |  1 +
 ForgeSVN/forgesvn/widgets.py                              |  1 +
 ForgeSVN/setup.py                                         |  1 +
 ForgeShortUrl/forgeshorturl/main.py                       |  1 +
 ForgeShortUrl/forgeshorturl/model/shorturl.py             |  1 +
 ForgeShortUrl/forgeshorturl/tests/functional/test.py      |  1 +
 ForgeShortUrl/forgeshorturl/widgets/short_url.py          |  1 +
 ForgeShortUrl/setup.py                                    |  1 +
 ForgeTracker/forgetracker/command/fix_discussion.py       |  1 +
 ForgeTracker/forgetracker/config/resources.py             |  1 +
 ForgeTracker/forgetracker/import_support.py               |  1 +
 ForgeTracker/forgetracker/model/__init__.py               |  3 ++-
 ForgeTracker/forgetracker/model/ticket.py                 |  1 +
 ForgeTracker/forgetracker/plugins.py                      |  1 +
 ForgeTracker/forgetracker/search.py                       |  1 +
 ForgeTracker/forgetracker/site_stats.py                   |  1 +
 ForgeTracker/forgetracker/tasks.py                        |  1 +
 .../forgetracker/tests/command/test_fix_discussion.py     |  1 +
 ForgeTracker/forgetracker/tests/functional/test_rest.py   |  1 +
 ForgeTracker/forgetracker/tests/functional/test_root.py   |  1 +
 ForgeTracker/forgetracker/tests/test_app.py               |  1 +
 ForgeTracker/forgetracker/tests/test_tracker_roles.py     |  1 +
 ForgeTracker/forgetracker/tests/unit/__init__.py          |  1 +
 .../forgetracker/tests/unit/test_globals_model.py         |  1 +
 .../forgetracker/tests/unit/test_milestone_controller.py  |  1 +
 .../forgetracker/tests/unit/test_root_controller.py       |  1 +
 ForgeTracker/forgetracker/tests/unit/test_search.py       |  1 +
 .../tests/unit/test_ticket_custom_fields_form.py          |  1 +
 ForgeTracker/forgetracker/tests/unit/test_ticket_form.py  |  1 +
 ForgeTracker/forgetracker/tests/unit/test_ticket_model.py |  1 +
 ForgeTracker/forgetracker/tracker_main.py                 |  1 +
 ForgeTracker/forgetracker/widgets/admin.py                |  1 +
 ForgeTracker/forgetracker/widgets/admin_custom_fields.py  |  1 +
 ForgeTracker/forgetracker/widgets/bin_form.py             |  1 +
 ForgeTracker/forgetracker/widgets/ticket_form.py          |  1 +
 ForgeTracker/forgetracker/widgets/ticket_search.py        |  1 +
 ForgeTracker/setup.py                                     |  1 +
 ForgeUserStats/forgeuserstats/controllers/userstats.py    |  1 +
 ForgeUserStats/forgeuserstats/main.py                     |  5 +++--
 ForgeUserStats/forgeuserstats/model/stats.py              |  1 +
 ForgeUserStats/forgeuserstats/tests/test_model.py         |  1 +
 ForgeUserStats/forgeuserstats/tests/test_stats.py         |  1 +
 ForgeUserStats/forgeuserstats/widgets/forms.py            |  1 +
 ForgeUserStats/setup.py                                   |  1 +
 ForgeWiki/forgewiki/converters.py                         |  1 +
 ForgeWiki/forgewiki/model/__init__.py                     |  3 ++-
 ForgeWiki/forgewiki/model/wiki.py                         |  1 +
 ForgeWiki/forgewiki/tests/functional/test_rest.py         |  1 +
 ForgeWiki/forgewiki/tests/functional/test_root.py         |  1 +
 ForgeWiki/forgewiki/tests/test_app.py                     |  1 +
 ForgeWiki/forgewiki/tests/test_converters.py              |  1 +
 ForgeWiki/forgewiki/tests/test_models.py                  |  1 +
 ForgeWiki/forgewiki/tests/test_wiki_roles.py              |  1 +
 ForgeWiki/forgewiki/wiki_main.py                          |  1 +
 ForgeWiki/setup.py                                        |  1 +
 fuse/accessfs.py                                          |  1 +
 scripts/ApacheAccessHandler.py                            |  1 +
 scripts/add_user_to_group.py                              |  1 +
 scripts/changelog.py                                      |  1 +
 scripts/create-allura-sitemap.py                          |  1 +
 scripts/migrations/013-update-ordinals.py                 |  1 +
 .../migrations/015-add-neighborhood_id-to-blog-posts.py   |  1 +
 scripts/migrations/018-add-svn-checkout-url.py            |  1 +
 scripts/migrations/020-remove-wiki-title-slashes.py       |  1 +
 scripts/migrations/022-change-anon-display-name.py        |  1 +
 scripts/migrations/024-migrate-custom-profile-text.py     |  1 +
 scripts/migrations/025-add-is-nbhd-project.py             |  1 +
 scripts/migrations/026-install-activity-tool.py           |  1 +
 scripts/migrations/027-change-ticket-write-permissions.py |  1 +
 scripts/migrations/028-remove-svn-trees.py                |  1 +
 scripts/migrations/029-set-mailbox-queue_empty.py         |  1 +
 scripts/migrations/031-set-user-pending-to-false.py       |  1 +
 .../migrations/032-subscribe-merge-request-submitters.py  |  1 +
 scripts/migrations/033-change-comment-anon-permissions.py |  1 +
 .../034-update_subscriptions_ticket_and_mr_titles.py      |  1 +
 scripts/new_ticket.py                                     |  1 +
 scripts/perf/benchmark-scm.py                             |  1 +
 scripts/perf/call_count.py                                |  1 +
 scripts/perf/generate-projects.py                         |  1 +
 scripts/perf/load-up-forum.py                             |  1 +
 scripts/perf/md_perf.py                                   |  1 +
 scripts/perf/parse_timings.py                             |  1 +
 scripts/perf/sstress.py                                   |  1 +
 scripts/perf/test_git_lcd.py                              |  1 +
 scripts/project-import.py                                 |  1 +
 scripts/publicize-neighborhood.py                         |  1 +
 scripts/rethumb.py                                        |  1 +
 scripts/scrub-allura-data.py                              |  1 +
 scripts/teamforge-import.py                               |  1 +
 scripts/trac_export.py                                    |  1 +
 scripts/trac_export_wiki.py                               |  1 +
 scripts/trac_import.py                                    |  1 +
 scripts/wiki-copy.py                                      |  1 +
 413 files changed, 446 insertions(+), 33 deletions(-)

diff --git a/Allura/allura/__init__.py b/Allura/allura/__init__.py
index 87deecd..f5270ce 100644
--- a/Allura/allura/__init__.py
+++ b/Allura/allura/__init__.py
@@ -19,6 +19,7 @@
 
 """The allura package"""
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg.support.registry import StackedObjectProxy
 
 credentials = StackedObjectProxy(name='credentials')
diff --git a/Allura/allura/app.py b/Allura/allura/app.py
index 478b48f..26b21f3 100644
--- a/Allura/allura/app.py
+++ b/Allura/allura/app.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import logging
 from urllib import basejoin
@@ -877,7 +878,7 @@ class DefaultAdminController(BaseController, AdminControllerMixin):
         """Render the permissions management web page.
 
         """
-        from ext.admin.widgets import PermissionCard, BlockUser, BlockList
+        from .ext.admin.widgets import PermissionCard, BlockUser, BlockList
         c.card = PermissionCard()
         c.block_user = BlockUser()
         c.block_list = BlockList()
diff --git a/Allura/allura/command/__init__.py b/Allura/allura/command/__init__.py
index d6d0c92..91bff33 100644
--- a/Allura/allura/command/__init__.py
+++ b/Allura/allura/command/__init__.py
@@ -16,13 +16,14 @@
 #       under the License.
 
 from __future__ import unicode_literals
-from base import Command
-from show_models import ShowModelsCommand, ReindexCommand, EnsureIndexCommand
-from script import ScriptCommand, SetToolAccessCommand
-from smtp_server import SMTPServerCommand
-from create_neighborhood import CreateNeighborhoodCommand, UpdateNeighborhoodCommand
-from create_trove_categories import CreateTroveCategoriesCommand
-from set_neighborhood_features import SetNeighborhoodFeaturesCommand
+from __future__ import absolute_import
+from .base import Command
+from .show_models import ShowModelsCommand, ReindexCommand, EnsureIndexCommand
+from .script import ScriptCommand, SetToolAccessCommand
+from .smtp_server import SMTPServerCommand
+from .create_neighborhood import CreateNeighborhoodCommand, UpdateNeighborhoodCommand
+from .create_trove_categories import CreateTroveCategoriesCommand
+from .set_neighborhood_features import SetNeighborhoodFeaturesCommand
 
 __all__ = [
     'Command', 'ShowModelsCommand', 'ReindexCommand', 'EnsureIndexCommand', 'ScriptCommand', 'SetToolAccessCommand',
diff --git a/Allura/allura/command/base.py b/Allura/allura/command/base.py
index 470a509..f7fd693 100644
--- a/Allura/allura/command/base.py
+++ b/Allura/allura/command/base.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import logging
 import shlex
diff --git a/Allura/allura/command/create_neighborhood.py b/Allura/allura/command/create_neighborhood.py
index e1dc85a..85b3319 100644
--- a/Allura/allura/command/create_neighborhood.py
+++ b/Allura/allura/command/create_neighborhood.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 from . import base
diff --git a/Allura/allura/command/create_trove_categories.py b/Allura/allura/command/create_trove_categories.py
index da28728..aa3bb99 100644
--- a/Allura/allura/command/create_trove_categories.py
+++ b/Allura/allura/command/create_trove_categories.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 import sys
 import logging
diff --git a/Allura/allura/command/reclone_repo.py b/Allura/allura/command/reclone_repo.py
index abbf9fb..a7d60fe 100644
--- a/Allura/allura/command/reclone_repo.py
+++ b/Allura/allura/command/reclone_repo.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import warnings
 
 from tg import tmpl_context as c
diff --git a/Allura/allura/command/script.py b/Allura/allura/command/script.py
index 29e030b..f9767e2 100644
--- a/Allura/allura/command/script.py
+++ b/Allura/allura/command/script.py
@@ -17,6 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import sys
 import os.path
 import cProfile
diff --git a/Allura/allura/command/set_neighborhood_features.py b/Allura/allura/command/set_neighborhood_features.py
index b10f9fd..a4d48fb 100644
--- a/Allura/allura/command/set_neighborhood_features.py
+++ b/Allura/allura/command/set_neighborhood_features.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from ast import literal_eval
 
 from allura.command import base
diff --git a/Allura/allura/command/show_models.py b/Allura/allura/command/show_models.py
index c9ad171..50c5114 100644
--- a/Allura/allura/command/show_models.py
+++ b/Allura/allura/command/show_models.py
@@ -17,6 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import sys
 from collections import defaultdict
 from contextlib import contextmanager
diff --git a/Allura/allura/command/smtp_server.py b/Allura/allura/command/smtp_server.py
index 4036084..535560f 100644
--- a/Allura/allura/command/smtp_server.py
+++ b/Allura/allura/command/smtp_server.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import smtpd
 import asyncore
 
diff --git a/Allura/allura/command/taskd.py b/Allura/allura/command/taskd.py
index 34c7e6b..b4c97d8 100644
--- a/Allura/allura/command/taskd.py
+++ b/Allura/allura/command/taskd.py
@@ -17,6 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import logging
 import os
 import time
@@ -33,7 +34,7 @@ from paste.deploy import loadapp
 from paste.deploy.converters import asint
 from webob import Request
 
-import base
+from . import base
 
 faulthandler.enable()
 
diff --git a/Allura/allura/command/taskd_cleanup.py b/Allura/allura/command/taskd_cleanup.py
index 3ce1421..4c50737 100644
--- a/Allura/allura/command/taskd_cleanup.py
+++ b/Allura/allura/command/taskd_cleanup.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import time
 import signal
@@ -24,7 +25,7 @@ import subprocess
 from ming.orm.ormsession import ThreadLocalORMSession
 
 from allura import model as M
-import base
+from . import base
 
 
 class TaskdCleanupCommand(base.Command):
diff --git a/Allura/allura/config/app_cfg.py b/Allura/allura/config/app_cfg.py
index 547403b..9e8d023 100644
--- a/Allura/allura/config/app_cfg.py
+++ b/Allura/allura/config/app_cfg.py
@@ -31,6 +31,7 @@ convert them into boolean, for example, you should use the
 
 """
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from functools import partial
 
diff --git a/Allura/allura/config/environment.py b/Allura/allura/config/environment.py
index e6ea993..1e7ef12 100644
--- a/Allura/allura/config/environment.py
+++ b/Allura/allura/config/environment.py
@@ -20,6 +20,7 @@
 """WSGI environment setup for allura."""
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from allura.config.app_cfg import base_config
 
 __all__ = ['load_environment']
diff --git a/Allura/allura/config/middleware.py b/Allura/allura/config/middleware.py
index e4f57f8..8c63f79 100644
--- a/Allura/allura/config/middleware.py
+++ b/Allura/allura/config/middleware.py
@@ -20,6 +20,7 @@
 """WSGI middleware initialization for the allura application."""
 from __future__ import unicode_literals
 
+from __future__ import absolute_import
 import ast
 import importlib
 import mimetypes
diff --git a/Allura/allura/config/resources.py b/Allura/allura/config/resources.py
index cf683d3..bbc52f8 100644
--- a/Allura/allura/config/resources.py
+++ b/Allura/allura/config/resources.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import logging
 
diff --git a/Allura/allura/controllers/attachments.py b/Allura/allura/controllers/attachments.py
index 9c762c7..e57e16a 100644
--- a/Allura/allura/controllers/attachments.py
+++ b/Allura/allura/controllers/attachments.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from urllib import unquote
 from webob import exc
 
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 002ae8a..496232c 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import os
 from datetime import datetime, timedelta
diff --git a/Allura/allura/controllers/base.py b/Allura/allura/controllers/base.py
index 902ffa7..b47d4c0 100644
--- a/Allura/allura/controllers/base.py
+++ b/Allura/allura/controllers/base.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 from tg import expose
diff --git a/Allura/allura/controllers/basetest_project_root.py b/Allura/allura/controllers/basetest_project_root.py
index ca2b4b6..89a3168 100644
--- a/Allura/allura/controllers/basetest_project_root.py
+++ b/Allura/allura/controllers/basetest_project_root.py
@@ -19,6 +19,7 @@
 
 """Main Controller"""
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from urllib import unquote
 
diff --git a/Allura/allura/controllers/discuss.py b/Allura/allura/controllers/discuss.py
index 0ec6a1a..c3c4d1b 100644
--- a/Allura/allura/controllers/discuss.py
+++ b/Allura/allura/controllers/discuss.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from urllib import unquote
 from datetime import datetime
 import logging
@@ -33,7 +34,7 @@ from ming.odm import session
 from ming.utils import LazyProperty
 
 from allura import model as M
-from base import BaseController
+from .base import BaseController
 from allura.lib import utils
 from allura.lib import helpers as h
 from allura.lib.decorators import require_post, memorable_forget
diff --git a/Allura/allura/controllers/error.py b/Allura/allura/controllers/error.py
index 599a8eb..1f2c7ed 100644
--- a/Allura/allura/controllers/error.py
+++ b/Allura/allura/controllers/error.py
@@ -20,6 +20,7 @@
 """Error controller"""
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import request, expose
 
 __all__ = ['ErrorController']
diff --git a/Allura/allura/controllers/feed.py b/Allura/allura/controllers/feed.py
index 5801f3a..6fadd8e 100644
--- a/Allura/allura/controllers/feed.py
+++ b/Allura/allura/controllers/feed.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import expose, validate, request, response
 from tg.decorators import without_trailing_slash
 from formencode import validators as V
diff --git a/Allura/allura/controllers/project.py b/Allura/allura/controllers/project.py
index 79fd453..f8fd627 100644
--- a/Allura/allura/controllers/project.py
+++ b/Allura/allura/controllers/project.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 import logging
 from datetime import datetime, timedelta
diff --git a/Allura/allura/controllers/repository.py b/Allura/allura/controllers/repository.py
index 13fa7af..93d746f 100644
--- a/Allura/allura/controllers/repository.py
+++ b/Allura/allura/controllers/repository.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import logging
 import difflib
diff --git a/Allura/allura/controllers/rest.py b/Allura/allura/controllers/rest.py
index 532a073..7e12731 100644
--- a/Allura/allura/controllers/rest.py
+++ b/Allura/allura/controllers/rest.py
@@ -19,6 +19,7 @@
 
 """REST Controller"""
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from urllib import unquote
 
diff --git a/Allura/allura/controllers/root.py b/Allura/allura/controllers/root.py
index b8a41a6..885383e 100644
--- a/Allura/allura/controllers/root.py
+++ b/Allura/allura/controllers/root.py
@@ -19,6 +19,7 @@
 
 """Main Controller"""
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from string import Template
 
diff --git a/Allura/allura/controllers/search.py b/Allura/allura/controllers/search.py
index 3039ba2..3e55708 100644
--- a/Allura/allura/controllers/search.py
+++ b/Allura/allura/controllers/search.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import expose, validate, request
 from tg.decorators import with_trailing_slash, without_trailing_slash
 from formencode import validators as V
diff --git a/Allura/allura/controllers/site_admin.py b/Allura/allura/controllers/site_admin.py
index 6674133..1d1d158 100644
--- a/Allura/allura/controllers/site_admin.py
+++ b/Allura/allura/controllers/site_admin.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 import logging
 from datetime import datetime, timedelta
diff --git a/Allura/allura/controllers/static.py b/Allura/allura/controllers/static.py
index 9cddb41..fd5404b 100644
--- a/Allura/allura/controllers/static.py
+++ b/Allura/allura/controllers/static.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from cStringIO import StringIO
 
 from tg import expose
diff --git a/Allura/allura/controllers/task.py b/Allura/allura/controllers/task.py
index 1429ac9..209aafc 100644
--- a/Allura/allura/controllers/task.py
+++ b/Allura/allura/controllers/task.py
@@ -18,6 +18,7 @@
 
 from __future__ import unicode_literals
 
+from __future__ import absolute_import
 import six
 
 
diff --git a/Allura/allura/controllers/trovecategories.py b/Allura/allura/controllers/trovecategories.py
index 81132da..d793147 100644
--- a/Allura/allura/controllers/trovecategories.py
+++ b/Allura/allura/controllers/trovecategories.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 from collections import OrderedDict
 
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index e593bba..79544f3 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import re
 import os
diff --git a/Allura/allura/ext/admin/widgets.py b/Allura/allura/ext/admin/widgets.py
index 3666bb8..82b3962 100644
--- a/Allura/allura/ext/admin/widgets.py
+++ b/Allura/allura/ext/admin/widgets.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 
 import ew as ew_core
diff --git a/Allura/allura/ext/personal_dashboard/dashboard_main.py b/Allura/allura/ext/personal_dashboard/dashboard_main.py
index 20fed9d..15f9f8f 100644
--- a/Allura/allura/ext/personal_dashboard/dashboard_main.py
+++ b/Allura/allura/ext/personal_dashboard/dashboard_main.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 from tg import tmpl_context as c, app_globals as g
diff --git a/Allura/allura/ext/project_home/project_main.py b/Allura/allura/ext/project_home/project_main.py
index 37cbd2e..c25acdd 100644
--- a/Allura/allura/ext/project_home/project_main.py
+++ b/Allura/allura/ext/project_home/project_main.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 import pkg_resources
diff --git a/Allura/allura/ext/search/search_main.py b/Allura/allura/ext/search/search_main.py
index 177354b..98abc4a 100644
--- a/Allura/allura/ext/search/search_main.py
+++ b/Allura/allura/ext/search/search_main.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 import pkg_resources
diff --git a/Allura/allura/ext/user_profile/user_main.py b/Allura/allura/ext/user_profile/user_main.py
index f99b608..bf96096 100644
--- a/Allura/allura/ext/user_profile/user_main.py
+++ b/Allura/allura/ext/user_profile/user_main.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 import pkg_resources
diff --git a/Allura/allura/lib/AsciiDammit.py b/Allura/allura/lib/AsciiDammit.py
index 80b1154..df0effa 100644
--- a/Allura/allura/lib/AsciiDammit.py
+++ b/Allura/allura/lib/AsciiDammit.py
@@ -19,6 +19,7 @@ all rights in this work otherwise reserved under copyright.
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 __author__ = "Leonard Richardson (leonardr@segfault.org)"
 __version__ = "$Revision: 1.3 $"
 __date__ = "$Date: 2009/04/28 10:45:03 $"
diff --git a/Allura/allura/lib/app_globals.py b/Allura/allura/lib/app_globals.py
index b16190a..f6a85e4 100644
--- a/Allura/allura/lib/app_globals.py
+++ b/Allura/allura/lib/app_globals.py
@@ -21,6 +21,7 @@
 """The application's Globals object"""
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import cgi
 import hashlib
diff --git a/Allura/allura/lib/base.py b/Allura/allura/lib/base.py
index 5cff792..de91eb1 100644
--- a/Allura/allura/lib/base.py
+++ b/Allura/allura/lib/base.py
@@ -19,6 +19,7 @@
 
 """The base Controller API."""
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import TGController
 
 __all__ = ['WsgiDispatchController']
diff --git a/Allura/allura/lib/custom_middleware.py b/Allura/allura/lib/custom_middleware.py
index d3f191e..86d5d02 100644
--- a/Allura/allura/lib/custom_middleware.py
+++ b/Allura/allura/lib/custom_middleware.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import re
 import logging
diff --git a/Allura/allura/lib/decorators.py b/Allura/allura/lib/decorators.py
index 95ab5a9..f018fa3 100644
--- a/Allura/allura/lib/decorators.py
+++ b/Allura/allura/lib/decorators.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import inspect
 import sys
 import json
diff --git a/Allura/allura/lib/diff.py b/Allura/allura/lib/diff.py
index b3c82e0..e23d944 100644
--- a/Allura/allura/lib/diff.py
+++ b/Allura/allura/lib/diff.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import difflib
 
 import six
diff --git a/Allura/allura/lib/exceptions.py b/Allura/allura/lib/exceptions.py
index 6b3ba28..ed7ef0b 100644
--- a/Allura/allura/lib/exceptions.py
+++ b/Allura/allura/lib/exceptions.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import webob.exc
 from formencode import Invalid
 
diff --git a/Allura/allura/lib/gravatar.py b/Allura/allura/lib/gravatar.py
index b678d14..9639b87 100644
--- a/Allura/allura/lib/gravatar.py
+++ b/Allura/allura/lib/gravatar.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 import urllib
 import hashlib
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index 419a9b8..a2fc96a 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import base64
 import sys
 import os
diff --git a/Allura/allura/lib/import_api.py b/Allura/allura/lib/import_api.py
index 95e214a..f061fed 100644
--- a/Allura/allura/lib/import_api.py
+++ b/Allura/allura/lib/import_api.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import urllib
 import urllib2
 import urlparse
diff --git a/Allura/allura/lib/macro.py b/Allura/allura/lib/macro.py
index b0c7f46..016fbfe 100644
--- a/Allura/allura/lib/macro.py
+++ b/Allura/allura/lib/macro.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import cgi
 import random
 import shlex
diff --git a/Allura/allura/lib/mail_util.py b/Allura/allura/lib/mail_util.py
index 7e09526..eb89c15 100644
--- a/Allura/allura/lib/mail_util.py
+++ b/Allura/allura/lib/mail_util.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 import logging
 import smtplib
diff --git a/Allura/allura/lib/markdown_extensions.py b/Allura/allura/lib/markdown_extensions.py
index 59233fd..eb876d3 100644
--- a/Allura/allura/lib/markdown_extensions.py
+++ b/Allura/allura/lib/markdown_extensions.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 import logging
 from urlparse import urljoin
diff --git a/Allura/allura/lib/multifactor.py b/Allura/allura/lib/multifactor.py
index adcb0eb..c21b197 100644
--- a/Allura/allura/lib/multifactor.py
+++ b/Allura/allura/lib/multifactor.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import logging
 import random
diff --git a/Allura/allura/lib/package_path_loader.py b/Allura/allura/lib/package_path_loader.py
index 6b6a8c1..2a752f9 100644
--- a/Allura/allura/lib/package_path_loader.py
+++ b/Allura/allura/lib/package_path_loader.py
@@ -123,6 +123,7 @@ The positioners are:
 
 """
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import pkg_resources
 import os
 
diff --git a/Allura/allura/lib/patches.py b/Allura/allura/lib/patches.py
index a7a4dcd..c419954 100644
--- a/Allura/allura/lib/patches.py
+++ b/Allura/allura/lib/patches.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 
 import webob
diff --git a/Allura/allura/lib/phone/__init__.py b/Allura/allura/lib/phone/__init__.py
index acb567c..b13bf6d 100644
--- a/Allura/allura/lib/phone/__init__.py
+++ b/Allura/allura/lib/phone/__init__.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 log = logging.getLogger(__name__)
diff --git a/Allura/allura/lib/phone/nexmo.py b/Allura/allura/lib/phone/nexmo.py
index f621da9..9b4d338 100644
--- a/Allura/allura/lib/phone/nexmo.py
+++ b/Allura/allura/lib/phone/nexmo.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from urlparse import urljoin
 import cgi
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index 5c09d53..085726b 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -19,6 +19,7 @@
 Allura plugins for authentication and project registration
 '''
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 import os
 import logging
diff --git a/Allura/allura/lib/repository.py b/Allura/allura/lib/repository.py
index 538028f..1ff9778 100644
--- a/Allura/allura/lib/repository.py
+++ b/Allura/allura/lib/repository.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from urllib import quote
 
diff --git a/Allura/allura/lib/search.py b/Allura/allura/lib/search.py
index 887e8c2..ac45ee4 100644
--- a/Allura/allura/lib/search.py
+++ b/Allura/allura/lib/search.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 import socket
 from logging import getLogger
diff --git a/Allura/allura/lib/solr.py b/Allura/allura/lib/solr.py
index 5ad5979..ab5390d 100644
--- a/Allura/allura/lib/solr.py
+++ b/Allura/allura/lib/solr.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import shlex
 import logging
 
diff --git a/Allura/allura/lib/spam/__init__.py b/Allura/allura/lib/spam/__init__.py
index 793999d..a3c45b3 100644
--- a/Allura/allura/lib/spam/__init__.py
+++ b/Allura/allura/lib/spam/__init__.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from copy import copy
 
diff --git a/Allura/allura/lib/spam/akismetfilter.py b/Allura/allura/lib/spam/akismetfilter.py
index a6e2115..b737ef7 100644
--- a/Allura/allura/lib/spam/akismetfilter.py
+++ b/Allura/allura/lib/spam/akismetfilter.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 from tg import request
diff --git a/Allura/allura/lib/spam/stopforumspamfilter.py b/Allura/allura/lib/spam/stopforumspamfilter.py
index b8af127..09bdba6 100644
--- a/Allura/allura/lib/spam/stopforumspamfilter.py
+++ b/Allura/allura/lib/spam/stopforumspamfilter.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import csv
 from sys import getsizeof
diff --git a/Allura/allura/lib/utils.py b/Allura/allura/lib/utils.py
index cedc50d..6e2322c 100644
--- a/Allura/allura/lib/utils.py
+++ b/Allura/allura/lib/utils.py
@@ -16,6 +16,7 @@
 #       under the License.
 from __future__ import unicode_literals
 
+from __future__ import absolute_import
 import base64
 import operator
 from contextlib import contextmanager
diff --git a/Allura/allura/lib/validators.py b/Allura/allura/lib/validators.py
index c92535b..ffc1a2a 100644
--- a/Allura/allura/lib/validators.py
+++ b/Allura/allura/lib/validators.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 import re
 from bson import ObjectId
diff --git a/Allura/allura/lib/widgets/analytics.py b/Allura/allura/lib/widgets/analytics.py
index 08f5cb0..d02ed42 100644
--- a/Allura/allura/lib/widgets/analytics.py
+++ b/Allura/allura/lib/widgets/analytics.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import ew
 
 
diff --git a/Allura/allura/lib/widgets/auth_widgets.py b/Allura/allura/lib/widgets/auth_widgets.py
index 28b916a..a257599 100644
--- a/Allura/allura/lib/widgets/auth_widgets.py
+++ b/Allura/allura/lib/widgets/auth_widgets.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import ew as ew_core
 import ew.jinja2_ew as ew
 from ew.core import validator
diff --git a/Allura/allura/lib/widgets/discuss.py b/Allura/allura/lib/widgets/discuss.py
index 703718c..1979901 100644
--- a/Allura/allura/lib/widgets/discuss.py
+++ b/Allura/allura/lib/widgets/discuss.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from formencode import validators as fev
 
 import json
diff --git a/Allura/allura/lib/widgets/form_fields.py b/Allura/allura/lib/widgets/form_fields.py
index 893f1fa..0ee7067 100644
--- a/Allura/allura/lib/widgets/form_fields.py
+++ b/Allura/allura/lib/widgets/form_fields.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 from tg import request, url
 import json
diff --git a/Allura/allura/lib/widgets/forms.py b/Allura/allura/lib/widgets/forms.py
index 0c8fc80..4b3e9e4 100644
--- a/Allura/allura/lib/widgets/forms.py
+++ b/Allura/allura/lib/widgets/forms.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import warnings
 
diff --git a/Allura/allura/lib/widgets/macros.py b/Allura/allura/lib/widgets/macros.py
index a709ac4..3926311 100644
--- a/Allura/allura/lib/widgets/macros.py
+++ b/Allura/allura/lib/widgets/macros.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import ew
 
 
diff --git a/Allura/allura/lib/widgets/oauth_widgets.py b/Allura/allura/lib/widgets/oauth_widgets.py
index b73c92c..b40158d 100644
--- a/Allura/allura/lib/widgets/oauth_widgets.py
+++ b/Allura/allura/lib/widgets/oauth_widgets.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import ew as ew_core
 import ew.jinja2_ew as ew
 
diff --git a/Allura/allura/lib/widgets/project_list.py b/Allura/allura/lib/widgets/project_list.py
index ad472f5..71a6b78 100644
--- a/Allura/allura/lib/widgets/project_list.py
+++ b/Allura/allura/lib/widgets/project_list.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import ew as ew_core
 import ew.jinja2_ew as ew
 
diff --git a/Allura/allura/lib/widgets/repo.py b/Allura/allura/lib/widgets/repo.py
index ecf5b4b..4514f69 100644
--- a/Allura/allura/lib/widgets/repo.py
+++ b/Allura/allura/lib/widgets/repo.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import ew as ew_core
 import ew.jinja2_ew as ew
 
diff --git a/Allura/allura/lib/widgets/search.py b/Allura/allura/lib/widgets/search.py
index 9ed6bf7..ddac9c5 100644
--- a/Allura/allura/lib/widgets/search.py
+++ b/Allura/allura/lib/widgets/search.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import ew as ew_core
 import ew.jinja2_ew as ew
 import jinja2
diff --git a/Allura/allura/lib/widgets/subscriptions.py b/Allura/allura/lib/widgets/subscriptions.py
index 7b3829b..2118041 100644
--- a/Allura/allura/lib/widgets/subscriptions.py
+++ b/Allura/allura/lib/widgets/subscriptions.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import ew as ew_core
 import ew.jinja2_ew as ew
 from tg import tmpl_context as c
diff --git a/Allura/allura/lib/widgets/user_profile.py b/Allura/allura/lib/widgets/user_profile.py
index a4089c1..bc517fa 100644
--- a/Allura/allura/lib/widgets/user_profile.py
+++ b/Allura/allura/lib/widgets/user_profile.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import re
 
diff --git a/Allura/allura/lib/widgets/vote.py b/Allura/allura/lib/widgets/vote.py
index 39ea618..1660fb4 100644
--- a/Allura/allura/lib/widgets/vote.py
+++ b/Allura/allura/lib/widgets/vote.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import ew as ew_core
 import ew.jinja2_ew as ew
 
diff --git a/Allura/allura/model/__init__.py b/Allura/allura/model/__init__.py
index 50bc8e1..72bab45 100644
--- a/Allura/allura/model/__init__.py
+++ b/Allura/allura/model/__init__.py
@@ -20,6 +20,7 @@
 """The application's model objects"""
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from .neighborhood import Neighborhood, NeighborhoodFile
 from .project import Project, ProjectCategory, TroveCategory, ProjectFile, AppConfig
 from .index import ArtifactReference, Shortlink
diff --git a/Allura/allura/model/artifact.py b/Allura/allura/model/artifact.py
index 2094270..37425fa 100644
--- a/Allura/allura/model/artifact.py
+++ b/Allura/allura/model/artifact.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from collections import defaultdict
 from datetime import datetime
@@ -45,7 +46,7 @@ from .types import ACL, MarkdownCache
 from .project import AppConfig
 from .notification import MailFooter
 
-from filesystem import File
+from .filesystem import File
 
 log = logging.getLogger(__name__)
 
diff --git a/Allura/allura/model/attachments.py b/Allura/allura/model/attachments.py
index b62cd80..36a8f66 100644
--- a/Allura/allura/model/attachments.py
+++ b/Allura/allura/model/attachments.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 from ming.orm import FieldProperty
 from ming import schema as S
diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index 9abe552..28fc1b8 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import calendar
 from urlparse import urlparse
diff --git a/Allura/allura/model/discuss.py b/Allura/allura/model/discuss.py
index c0b559a..708f974 100644
--- a/Allura/allura/model/discuss.py
+++ b/Allura/allura/model/discuss.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import logging
 from datetime import datetime
diff --git a/Allura/allura/model/filesystem.py b/Allura/allura/model/filesystem.py
index 70f335b..4bc9bf2 100644
--- a/Allura/allura/model/filesystem.py
+++ b/Allura/allura/model/filesystem.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import re
 from cStringIO import StringIO
diff --git a/Allura/allura/model/index.py b/Allura/allura/model/index.py
index 02edea3..b55e186 100644
--- a/Allura/allura/model/index.py
+++ b/Allura/allura/model/index.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 import logging
 from itertools import groupby
diff --git a/Allura/allura/model/monq_model.py b/Allura/allura/model/monq_model.py
index b715f33..60edf10 100644
--- a/Allura/allura/model/monq_model.py
+++ b/Allura/allura/model/monq_model.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import sys
 import time
 import traceback
diff --git a/Allura/allura/model/multifactor.py b/Allura/allura/model/multifactor.py
index d67bcb1..433c246 100644
--- a/Allura/allura/model/multifactor.py
+++ b/Allura/allura/model/multifactor.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 from ming import schema as S
diff --git a/Allura/allura/model/neighborhood.py b/Allura/allura/model/neighborhood.py
index f030077..6a08117 100644
--- a/Allura/allura/model/neighborhood.py
+++ b/Allura/allura/model/neighborhood.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 import json
 import logging
diff --git a/Allura/allura/model/notification.py b/Allura/allura/model/notification.py
index e085897..4c41129 100644
--- a/Allura/allura/model/notification.py
+++ b/Allura/allura/model/notification.py
@@ -35,6 +35,7 @@ Periodically:
 '''
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from bson import ObjectId
 from datetime import datetime, timedelta
diff --git a/Allura/allura/model/oauth.py b/Allura/allura/model/oauth.py
index e2016ae..7dc5da9 100644
--- a/Allura/allura/model/oauth.py
+++ b/Allura/allura/model/oauth.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 import oauth2 as oauth
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index d6461b5..d8d1764 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -17,6 +17,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from calendar import timegm
 from collections import Counter, OrderedDict
@@ -60,7 +61,7 @@ from .timeline import ActivityNode, ActivityObject
 from .types import ACL, ACE
 from .monq_model import MonQTask
 
-from filesystem import File
+from .filesystem import File
 
 log = logging.getLogger(__name__)
 
diff --git a/Allura/allura/model/repo_refresh.py b/Allura/allura/model/repo_refresh.py
index 790cba3..74c005d 100644
--- a/Allura/allura/model/repo_refresh.py
+++ b/Allura/allura/model/repo_refresh.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from itertools import chain
 from cPickle import dumps
diff --git a/Allura/allura/model/repository.py b/Allura/allura/model/repository.py
index d4708d1..44adc5e 100644
--- a/Allura/allura/model/repository.py
+++ b/Allura/allura/model/repository.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 import os
 import stat
diff --git a/Allura/allura/model/session.py b/Allura/allura/model/session.py
index bff64e9..cb4255a 100644
--- a/Allura/allura/model/session.py
+++ b/Allura/allura/model/session.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import pymongo
 from collections import defaultdict
diff --git a/Allura/allura/model/stats.py b/Allura/allura/model/stats.py
index 9cee2e2..c5f07b8 100644
--- a/Allura/allura/model/stats.py
+++ b/Allura/allura/model/stats.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from datetime import datetime
 from tg import config
 from paste.deploy.converters import asbool
diff --git a/Allura/allura/model/timeline.py b/Allura/allura/model/timeline.py
index 2a1a138..952b904 100644
--- a/Allura/allura/model/timeline.py
+++ b/Allura/allura/model/timeline.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import bson
 import logging
 
diff --git a/Allura/allura/model/types.py b/Allura/allura/model/types.py
index 60bb225..c235ff8 100644
--- a/Allura/allura/model/types.py
+++ b/Allura/allura/model/types.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from ming.base import Object
 from ming import schema as S
 
diff --git a/Allura/allura/model/webhook.py b/Allura/allura/model/webhook.py
index 5f923ca..7eae3ed 100644
--- a/Allura/allura/model/webhook.py
+++ b/Allura/allura/model/webhook.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import datetime as dt
 import json
 
diff --git a/Allura/allura/scripts/__init__.py b/Allura/allura/scripts/__init__.py
index 35779cc..5c15324 100644
--- a/Allura/allura/scripts/__init__.py
+++ b/Allura/allura/scripts/__init__.py
@@ -15,4 +15,5 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
-from scripttask import ScriptTask
+from __future__ import absolute_import
+from .scripttask import ScriptTask
diff --git a/Allura/allura/scripts/create_sitemap_files.py b/Allura/allura/scripts/create_sitemap_files.py
index 1fbe03a..8ed580e 100644
--- a/Allura/allura/scripts/create_sitemap_files.py
+++ b/Allura/allura/scripts/create_sitemap_files.py
@@ -30,6 +30,7 @@ things that would make it faster, if we need/want to.
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import os
 from datetime import datetime
 import argparse
diff --git a/Allura/allura/scripts/delete_projects.py b/Allura/allura/scripts/delete_projects.py
index 330fe01..4c8e985 100644
--- a/Allura/allura/scripts/delete_projects.py
+++ b/Allura/allura/scripts/delete_projects.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import argparse
 import logging
 
diff --git a/Allura/allura/scripts/disable_users.py b/Allura/allura/scripts/disable_users.py
index 63a91a5..ae0d6d6 100644
--- a/Allura/allura/scripts/disable_users.py
+++ b/Allura/allura/scripts/disable_users.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import argparse
 import logging
 import sys
diff --git a/Allura/allura/scripts/refresh_last_commits.py b/Allura/allura/scripts/refresh_last_commits.py
index 71a729e..179317c 100644
--- a/Allura/allura/scripts/refresh_last_commits.py
+++ b/Allura/allura/scripts/refresh_last_commits.py
@@ -17,6 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import argparse
 import logging
 from datetime import datetime
diff --git a/Allura/allura/scripts/refreshrepo.py b/Allura/allura/scripts/refreshrepo.py
index e1e9bf9..7144541 100644
--- a/Allura/allura/scripts/refreshrepo.py
+++ b/Allura/allura/scripts/refreshrepo.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import argparse
 import logging
 import faulthandler
diff --git a/Allura/allura/scripts/reindex_projects.py b/Allura/allura/scripts/reindex_projects.py
index 0e65538..e7b3afd 100644
--- a/Allura/allura/scripts/reindex_projects.py
+++ b/Allura/allura/scripts/reindex_projects.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import argparse
 import logging
 
diff --git a/Allura/allura/scripts/reindex_users.py b/Allura/allura/scripts/reindex_users.py
index ccd40c0..64c779b 100644
--- a/Allura/allura/scripts/reindex_users.py
+++ b/Allura/allura/scripts/reindex_users.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import argparse
 import logging
 
diff --git a/Allura/allura/scripts/scripttask.py b/Allura/allura/scripts/scripttask.py
index ec5e4b2..1281877 100644
--- a/Allura/allura/scripts/scripttask.py
+++ b/Allura/allura/scripts/scripttask.py
@@ -45,6 +45,7 @@ To call as a task::
 """
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import argparse
 import logging
 import shlex
diff --git a/Allura/allura/scripts/trac_export.py b/Allura/allura/scripts/trac_export.py
index f302186..d2180e8 100644
--- a/Allura/allura/scripts/trac_export.py
+++ b/Allura/allura/scripts/trac_export.py
@@ -19,6 +19,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import logging
 import sys
 import csv
diff --git a/Allura/allura/tasks/activity_tasks.py b/Allura/allura/tasks/activity_tasks.py
index 3dc5f77..0886699 100644
--- a/Allura/allura/tasks/activity_tasks.py
+++ b/Allura/allura/tasks/activity_tasks.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import app_globals as g
 from activitystream.storage.mingstorage import Activity
 
diff --git a/Allura/allura/tasks/admin_tasks.py b/Allura/allura/tasks/admin_tasks.py
index c3b6c26..c52c1ec 100644
--- a/Allura/allura/tasks/admin_tasks.py
+++ b/Allura/allura/tasks/admin_tasks.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import inspect
 
 from tg import tmpl_context as c
diff --git a/Allura/allura/tasks/event_tasks.py b/Allura/allura/tasks/event_tasks.py
index 8a2de35..fe537cd 100644
--- a/Allura/allura/tasks/event_tasks.py
+++ b/Allura/allura/tasks/event_tasks.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import absolute_import
 import sys
 
 from allura.lib.decorators import task, event_handler
diff --git a/Allura/allura/tasks/export_tasks.py b/Allura/allura/tasks/export_tasks.py
index 56a19d5..9614e28 100644
--- a/Allura/allura/tasks/export_tasks.py
+++ b/Allura/allura/tasks/export_tasks.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import os.path
 import logging
diff --git a/Allura/allura/tasks/index_tasks.py b/Allura/allura/tasks/index_tasks.py
index ef4b80f..07ce887 100644
--- a/Allura/allura/tasks/index_tasks.py
+++ b/Allura/allura/tasks/index_tasks.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import sys
 import logging
 from contextlib import contextmanager
diff --git a/Allura/allura/tasks/mail_tasks.py b/Allura/allura/tasks/mail_tasks.py
index f8f1cc0..d3827ae 100644
--- a/Allura/allura/tasks/mail_tasks.py
+++ b/Allura/allura/tasks/mail_tasks.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import HTMLParser
 import re
diff --git a/Allura/allura/tasks/notification_tasks.py b/Allura/allura/tasks/notification_tasks.py
index c74dd2c..9d83e43 100644
--- a/Allura/allura/tasks/notification_tasks.py
+++ b/Allura/allura/tasks/notification_tasks.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from allura.lib.decorators import task
 from allura.lib import utils
 from tg import tmpl_context as c
diff --git a/Allura/allura/tasks/repo_tasks.py b/Allura/allura/tasks/repo_tasks.py
index b4fb977..04e1a9f 100644
--- a/Allura/allura/tasks/repo_tasks.py
+++ b/Allura/allura/tasks/repo_tasks.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import shutil
 import logging
 import traceback
diff --git a/Allura/allura/tests/__init__.py b/Allura/allura/tests/__init__.py
index d557387..94ee329 100644
--- a/Allura/allura/tests/__init__.py
+++ b/Allura/allura/tests/__init__.py
@@ -20,6 +20,7 @@
 """Unit and functional test suite for allura."""
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import alluratest.controller
 
 # HACK: prevents test suite from crashing when running under the nose
diff --git a/Allura/allura/tests/decorators.py b/Allura/allura/tests/decorators.py
index c1bbcd7..647674f 100644
--- a/Allura/allura/tests/decorators.py
+++ b/Allura/allura/tests/decorators.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import sys
 import re
diff --git a/Allura/allura/tests/functional/test_admin.py b/Allura/allura/tests/functional/test_admin.py
index a05e85e..6db9053 100644
--- a/Allura/allura/tests/functional/test_admin.py
+++ b/Allura/allura/tests/functional/test_admin.py
@@ -17,6 +17,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import allura
 import pkg_resources
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index e48921d..0cef79e 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -17,6 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import calendar
 from datetime import datetime, time, timedelta
 from time import time as time_time
diff --git a/Allura/allura/tests/functional/test_discuss.py b/Allura/allura/tests/functional/test_discuss.py
index 64791da..51f84a1 100644
--- a/Allura/allura/tests/functional/test_discuss.py
+++ b/Allura/allura/tests/functional/test_discuss.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 from mock import patch
 from nose.tools import assert_in, assert_not_in, assert_equal, assert_false, assert_true, assert_raises
diff --git a/Allura/allura/tests/functional/test_feeds.py b/Allura/allura/tests/functional/test_feeds.py
index 16e3f5d..2d717cb 100644
--- a/Allura/allura/tests/functional/test_feeds.py
+++ b/Allura/allura/tests/functional/test_feeds.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from formencode.variabledecode import variable_encode
 
 from allura.tests import TestController
diff --git a/Allura/allura/tests/functional/test_gravatar.py b/Allura/allura/tests/functional/test_gravatar.py
index b07e4cd..f2235ed 100644
--- a/Allura/allura/tests/functional/test_gravatar.py
+++ b/Allura/allura/tests/functional/test_gravatar.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from urlparse import urlparse, parse_qs
 
 import tg
diff --git a/Allura/allura/tests/functional/test_home.py b/Allura/allura/tests/functional/test_home.py
index 8a5beb9..686b31e 100644
--- a/Allura/allura/tests/functional/test_home.py
+++ b/Allura/allura/tests/functional/test_home.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 import re
 import os
diff --git a/Allura/allura/tests/functional/test_nav.py b/Allura/allura/tests/functional/test_nav.py
index a50579f..a3c5fe5 100644
--- a/Allura/allura/tests/functional/test_nav.py
+++ b/Allura/allura/tests/functional/test_nav.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import mock
 import json
 from tg import config
diff --git a/Allura/allura/tests/functional/test_neighborhood.py b/Allura/allura/tests/functional/test_neighborhood.py
index 11e5074..5ed2a2a 100644
--- a/Allura/allura/tests/functional/test_neighborhood.py
+++ b/Allura/allura/tests/functional/test_neighborhood.py
@@ -17,6 +17,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 import os
 from cStringIO import StringIO
diff --git a/Allura/allura/tests/functional/test_personal_dashboard.py b/Allura/allura/tests/functional/test_personal_dashboard.py
index 01e3e8f..15a1821 100644
--- a/Allura/allura/tests/functional/test_personal_dashboard.py
+++ b/Allura/allura/tests/functional/test_personal_dashboard.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import pkg_resources
 import mock
 import tg
diff --git a/Allura/allura/tests/functional/test_rest.py b/Allura/allura/tests/functional/test_rest.py
index 892db1d..310d172 100644
--- a/Allura/allura/tests/functional/test_rest.py
+++ b/Allura/allura/tests/functional/test_rest.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import app_globals as g
 import mock
 from nose.tools import assert_equal, assert_in, assert_not_in
diff --git a/Allura/allura/tests/functional/test_root.py b/Allura/allura/tests/functional/test_root.py
index e9c630c..322f2bb 100644
--- a/Allura/allura/tests/functional/test_root.py
+++ b/Allura/allura/tests/functional/test_root.py
@@ -29,6 +29,7 @@ Please read http://pythonpaste.org/webtest/ for more information.
 
 """
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 from urllib import quote
 
diff --git a/Allura/allura/tests/functional/test_search.py b/Allura/allura/tests/functional/test_search.py
index 6a09f5c..5beff1e 100644
--- a/Allura/allura/tests/functional/test_search.py
+++ b/Allura/allura/tests/functional/test_search.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from mock import patch
 
 from tg import tmpl_context as c
diff --git a/Allura/allura/tests/functional/test_site_admin.py b/Allura/allura/tests/functional/test_site_admin.py
index 55c3155..93f30f2 100644
--- a/Allura/allura/tests/functional/test_site_admin.py
+++ b/Allura/allura/tests/functional/test_site_admin.py
@@ -17,6 +17,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 import datetime as dt
 import bson
diff --git a/Allura/allura/tests/functional/test_static.py b/Allura/allura/tests/functional/test_static.py
index 392af13..0e3eb58 100644
--- a/Allura/allura/tests/functional/test_static.py
+++ b/Allura/allura/tests/functional/test_static.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from allura.tests import TestController
 
 
diff --git a/Allura/allura/tests/functional/test_subscriber.py b/Allura/allura/tests/functional/test_subscriber.py
index aae83a3..6a90b64 100644
--- a/Allura/allura/tests/functional/test_subscriber.py
+++ b/Allura/allura/tests/functional/test_subscriber.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from allura.tests import TestController
 from allura.tests import decorators as td
 from allura.model.notification import Mailbox
diff --git a/Allura/allura/tests/functional/test_tool_list.py b/Allura/allura/tests/functional/test_tool_list.py
index 1bf57db..3f8a0b6 100644
--- a/Allura/allura/tests/functional/test_tool_list.py
+++ b/Allura/allura/tests/functional/test_tool_list.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from allura.tests import TestController
 from allura.tests import decorators as td
 
diff --git a/Allura/allura/tests/functional/test_trovecategory.py b/Allura/allura/tests/functional/test_trovecategory.py
index 8946043..1161044 100644
--- a/Allura/allura/tests/functional/test_trovecategory.py
+++ b/Allura/allura/tests/functional/test_trovecategory.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from bs4 import BeautifulSoup
 import mock
 
diff --git a/Allura/allura/tests/functional/test_user_profile.py b/Allura/allura/tests/functional/test_user_profile.py
index 5ef92a1..71e3848 100644
--- a/Allura/allura/tests/functional/test_user_profile.py
+++ b/Allura/allura/tests/functional/test_user_profile.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import mock
 import tg
 from nose.tools import assert_equal, assert_in, assert_not_in
diff --git a/Allura/allura/tests/model/test_artifact.py b/Allura/allura/tests/model/test_artifact.py
index e9d617b..e0d15d9 100644
--- a/Allura/allura/tests/model/test_artifact.py
+++ b/Allura/allura/tests/model/test_artifact.py
@@ -21,6 +21,7 @@
 Model tests for artifact
 """
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 from datetime import datetime
 
diff --git a/Allura/allura/tests/model/test_auth.py b/Allura/allura/tests/model/test_auth.py
index 57c36f6..79a7786 100644
--- a/Allura/allura/tests/model/test_auth.py
+++ b/Allura/allura/tests/model/test_auth.py
@@ -21,6 +21,7 @@
 Model tests for auth
 """
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from nose.tools import (
     with_setup,
     assert_equal,
diff --git a/Allura/allura/tests/model/test_discussion.py b/Allura/allura/tests/model/test_discussion.py
index 162c235..91ca97d 100644
--- a/Allura/allura/tests/model/test_discussion.py
+++ b/Allura/allura/tests/model/test_discussion.py
@@ -21,6 +21,7 @@
 Model tests for artifact
 """
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from cStringIO import StringIO
 import time
 from datetime import datetime, timedelta
diff --git a/Allura/allura/tests/model/test_filesystem.py b/Allura/allura/tests/model/test_filesystem.py
index b36f9a2..545945f 100644
--- a/Allura/allura/tests/model/test_filesystem.py
+++ b/Allura/allura/tests/model/test_filesystem.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 from unittest import TestCase
 from cStringIO import StringIO
diff --git a/Allura/allura/tests/model/test_monq.py b/Allura/allura/tests/model/test_monq.py
index e42c940..6ce7600 100644
--- a/Allura/allura/tests/model/test_monq.py
+++ b/Allura/allura/tests/model/test_monq.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import pprint
 from nose.tools import with_setup
 
diff --git a/Allura/allura/tests/model/test_neighborhood.py b/Allura/allura/tests/model/test_neighborhood.py
index bb62787..bd5801b 100644
--- a/Allura/allura/tests/model/test_neighborhood.py
+++ b/Allura/allura/tests/model/test_neighborhood.py
@@ -21,6 +21,7 @@
 Model tests for neighborhood
 """
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from nose.tools import with_setup
 
 from allura import model as M
diff --git a/Allura/allura/tests/model/test_notification.py b/Allura/allura/tests/model/test_notification.py
index 684d3be..ec2546a 100644
--- a/Allura/allura/tests/model/test_notification.py
+++ b/Allura/allura/tests/model/test_notification.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import unittest
 from datetime import timedelta
 import collections
diff --git a/Allura/allura/tests/model/test_oauth.py b/Allura/allura/tests/model/test_oauth.py
index d7e4ee6..831f3b3 100644
--- a/Allura/allura/tests/model/test_oauth.py
+++ b/Allura/allura/tests/model/test_oauth.py
@@ -19,6 +19,7 @@
 
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from nose.tools import with_setup, assert_equal, assert_not_equal
 
 from ming.odm import ThreadLocalORMSession
diff --git a/Allura/allura/tests/model/test_project.py b/Allura/allura/tests/model/test_project.py
index ea06c69..8c2db7c 100644
--- a/Allura/allura/tests/model/test_project.py
+++ b/Allura/allura/tests/model/test_project.py
@@ -21,6 +21,7 @@
 Model tests for project
 """
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from nose import with_setup
 from nose.tools import assert_equals, assert_in
 from tg import tmpl_context as c
diff --git a/Allura/allura/tests/model/test_repo.py b/Allura/allura/tests/model/test_repo.py
index f6f09bd..8eea5db 100644
--- a/Allura/allura/tests/model/test_repo.py
+++ b/Allura/allura/tests/model/test_repo.py
@@ -17,6 +17,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from datetime import datetime
 from collections import defaultdict, OrderedDict
 
diff --git a/Allura/allura/tests/model/test_timeline.py b/Allura/allura/tests/model/test_timeline.py
index 0ca22d5..eb28fbb 100644
--- a/Allura/allura/tests/model/test_timeline.py
+++ b/Allura/allura/tests/model/test_timeline.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from nose.tools import assert_equal
 
 from allura import model as M
diff --git a/Allura/allura/tests/scripts/test_create_sitemap_files.py b/Allura/allura/tests/scripts/test_create_sitemap_files.py
index e8be071..3852f82 100644
--- a/Allura/allura/tests/scripts/test_create_sitemap_files.py
+++ b/Allura/allura/tests/scripts/test_create_sitemap_files.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 from shutil import rmtree
 import xml.etree.ElementTree as ET
diff --git a/Allura/allura/tests/scripts/test_delete_projects.py b/Allura/allura/tests/scripts/test_delete_projects.py
index cbb4767..c7bf4d3 100644
--- a/Allura/allura/tests/scripts/test_delete_projects.py
+++ b/Allura/allura/tests/scripts/test_delete_projects.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from ming.odm import session, Mapper, ThreadLocalODMSession
 from mock import patch
 from tg import app_globals as g
diff --git a/Allura/allura/tests/scripts/test_reindexes.py b/Allura/allura/tests/scripts/test_reindexes.py
index 90ede90..3c8cd8a 100644
--- a/Allura/allura/tests/scripts/test_reindexes.py
+++ b/Allura/allura/tests/scripts/test_reindexes.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from nose.tools import assert_in, assert_equal
 from testfixtures import LogCapture
 
diff --git a/Allura/allura/tests/templates/jinja_master/test_lib.py b/Allura/allura/tests/templates/jinja_master/test_lib.py
index 8005fbc..8b27438 100644
--- a/Allura/allura/tests/templates/jinja_master/test_lib.py
+++ b/Allura/allura/tests/templates/jinja_master/test_lib.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import config, app_globals as g
 from mock import Mock
 from nose.tools import assert_equal
diff --git a/Allura/allura/tests/test_app.py b/Allura/allura/tests/test_app.py
index 8ea1b68..5fc443c 100644
--- a/Allura/allura/tests/test_app.py
+++ b/Allura/allura/tests/test_app.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 import mock
 from ming.base import Object
diff --git a/Allura/allura/tests/test_commands.py b/Allura/allura/tests/test_commands.py
index 22925b7..344ca39 100644
--- a/Allura/allura/tests/test_commands.py
+++ b/Allura/allura/tests/test_commands.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from nose.tools import assert_raises, assert_in
 from testfixtures import OutputCapture
 
diff --git a/Allura/allura/tests/test_decorators.py b/Allura/allura/tests/test_decorators.py
index 74777ab..9eba4a2 100644
--- a/Allura/allura/tests/test_decorators.py
+++ b/Allura/allura/tests/test_decorators.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import inspect
 from unittest import TestCase
 from mock import patch
diff --git a/Allura/allura/tests/test_diff.py b/Allura/allura/tests/test_diff.py
index 6b61cec..977fd69 100644
--- a/Allura/allura/tests/test_diff.py
+++ b/Allura/allura/tests/test_diff.py
@@ -17,6 +17,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import unittest
 
 from allura.lib.diff import HtmlSideBySideDiff
diff --git a/Allura/allura/tests/test_dispatch.py b/Allura/allura/tests/test_dispatch.py
index b80cead..b1af0ad 100644
--- a/Allura/allura/tests/test_dispatch.py
+++ b/Allura/allura/tests/test_dispatch.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from allura.tests import TestController
 
 app = None
diff --git a/Allura/allura/tests/test_globals.py b/Allura/allura/tests/test_globals.py
index 335f71d..70acceb 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -19,6 +19,7 @@
 
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 import os
 import allura
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index 873e82f..0c6d321 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from unittest import TestCase
 from os import path
 from datetime import datetime, timedelta
diff --git a/Allura/allura/tests/test_mail_util.py b/Allura/allura/tests/test_mail_util.py
index bdae63f..4b3d21e 100644
--- a/Allura/allura/tests/test_mail_util.py
+++ b/Allura/allura/tests/test_mail_util.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import unittest
 from email.MIMEMultipart import MIMEMultipart
 from email.MIMEText import MIMEText
diff --git a/Allura/allura/tests/test_markdown.py b/Allura/allura/tests/test_markdown.py
index 10f6a52..a276b67 100644
--- a/Allura/allura/tests/test_markdown.py
+++ b/Allura/allura/tests/test_markdown.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import unittest
 import mock
 
diff --git a/Allura/allura/tests/test_middlewares.py b/Allura/allura/tests/test_middlewares.py
index 67914b0..32793eb 100644
--- a/Allura/allura/tests/test_middlewares.py
+++ b/Allura/allura/tests/test_middlewares.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from mock import MagicMock, patch
 from datadiff.tools import assert_equal
 from nose.tools import assert_not_equal
diff --git a/Allura/allura/tests/test_multifactor.py b/Allura/allura/tests/test_multifactor.py
index 34bc53f..9644352 100644
--- a/Allura/allura/tests/test_multifactor.py
+++ b/Allura/allura/tests/test_multifactor.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import shutil
 import tempfile
 import textwrap
diff --git a/Allura/allura/tests/test_patches.py b/Allura/allura/tests/test_patches.py
index 8c19737..570850b 100644
--- a/Allura/allura/tests/test_patches.py
+++ b/Allura/allura/tests/test_patches.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import webob
 from mock import patch
 from nose.tools import (
diff --git a/Allura/allura/tests/test_plugin.py b/Allura/allura/tests/test_plugin.py
index 30d24e2..83c865f 100644
--- a/Allura/allura/tests/test_plugin.py
+++ b/Allura/allura/tests/test_plugin.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import datetime as dt
 import calendar
 
diff --git a/Allura/allura/tests/test_scripttask.py b/Allura/allura/tests/test_scripttask.py
index 58b8888..1daa844 100644
--- a/Allura/allura/tests/test_scripttask.py
+++ b/Allura/allura/tests/test_scripttask.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import unittest
 import mock
 
diff --git a/Allura/allura/tests/test_security.py b/Allura/allura/tests/test_security.py
index 1acb87f..28ab9ff 100644
--- a/Allura/allura/tests/test_security.py
+++ b/Allura/allura/tests/test_security.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 from nose.tools import assert_equal
 
diff --git a/Allura/allura/tests/test_tasks.py b/Allura/allura/tests/test_tasks.py
index 74c9372..85e21ca 100644
--- a/Allura/allura/tests/test_tasks.py
+++ b/Allura/allura/tests/test_tasks.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import operator
 import shutil
 import sys
diff --git a/Allura/allura/tests/test_utils.py b/Allura/allura/tests/test_utils.py
index feaf059..c34e7c0 100644
--- a/Allura/allura/tests/test_utils.py
+++ b/Allura/allura/tests/test_utils.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 import time
 import unittest
diff --git a/Allura/allura/tests/test_validators.py b/Allura/allura/tests/test_validators.py
index 4d75135..3e581cf 100644
--- a/Allura/allura/tests/test_validators.py
+++ b/Allura/allura/tests/test_validators.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import unittest
 import formencode as fe
 from mock import Mock, patch
diff --git a/Allura/allura/tests/test_webhooks.py b/Allura/allura/tests/test_webhooks.py
index 43f0cdf..adba095 100644
--- a/Allura/allura/tests/test_webhooks.py
+++ b/Allura/allura/tests/test_webhooks.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 import hmac
 import hashlib
diff --git a/Allura/allura/tests/tscript.py b/Allura/allura/tests/tscript.py
index 2f2be0f..f21b7d9 100644
--- a/Allura/allura/tests/tscript.py
+++ b/Allura/allura/tests/tscript.py
@@ -17,6 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import logging
 
 from allura import model as M
diff --git a/Allura/allura/tests/unit/__init__.py b/Allura/allura/tests/unit/__init__.py
index 27eb1e5..e541be8 100644
--- a/Allura/allura/tests/unit/__init__.py
+++ b/Allura/allura/tests/unit/__init__.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import absolute_import
 from alluratest.controller import setup_basic_test
 from allura.websetup.bootstrap import clear_all_database_tables
 
diff --git a/Allura/allura/tests/unit/controllers/test_auth.py b/Allura/allura/tests/unit/controllers/test_auth.py
index 6b83d2d..74c5aa4 100644
--- a/Allura/allura/tests/unit/controllers/test_auth.py
+++ b/Allura/allura/tests/unit/controllers/test_auth.py
@@ -17,6 +17,7 @@
 
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from mock import patch
 from allura.controllers.auth import AuthController
 
diff --git a/Allura/allura/tests/unit/controllers/test_discussion_moderation_controller.py b/Allura/allura/tests/unit/controllers/test_discussion_moderation_controller.py
index 7141df8..9c4d8c9 100644
--- a/Allura/allura/tests/unit/controllers/test_discussion_moderation_controller.py
+++ b/Allura/allura/tests/unit/controllers/test_discussion_moderation_controller.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from nose.tools import assert_equal
 from mock import Mock, patch
 from ming.orm import ThreadLocalORMSession, session
diff --git a/Allura/allura/tests/unit/controllers/test_dispatch_index.py b/Allura/allura/tests/unit/controllers/test_dispatch_index.py
index 48df41d..1e62be7 100644
--- a/Allura/allura/tests/unit/controllers/test_dispatch_index.py
+++ b/Allura/allura/tests/unit/controllers/test_dispatch_index.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from mock import Mock
 from allura.controllers.base import DispatchIndex, BaseController
 
diff --git a/Allura/allura/tests/unit/factories.py b/Allura/allura/tests/unit/factories.py
index 6e66e4e..1c9136c 100644
--- a/Allura/allura/tests/unit/factories.py
+++ b/Allura/allura/tests/unit/factories.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from functools import wraps
 
 from ming.orm import ThreadLocalORMSession
diff --git a/Allura/allura/tests/unit/patches.py b/Allura/allura/tests/unit/patches.py
index 700f1e0..f8818be 100644
--- a/Allura/allura/tests/unit/patches.py
+++ b/Allura/allura/tests/unit/patches.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from mock import Mock, patch
 from tg import tmpl_context as c
 
diff --git a/Allura/allura/tests/unit/phone/test_nexmo.py b/Allura/allura/tests/unit/phone/test_nexmo.py
index 9f4a165..f6999ad 100644
--- a/Allura/allura/tests/unit/phone/test_nexmo.py
+++ b/Allura/allura/tests/unit/phone/test_nexmo.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 from mock import patch
 from datadiff.tools import assert_equal
diff --git a/Allura/allura/tests/unit/phone/test_phone_service.py b/Allura/allura/tests/unit/phone/test_phone_service.py
index 7039285..8f60220 100644
--- a/Allura/allura/tests/unit/phone/test_phone_service.py
+++ b/Allura/allura/tests/unit/phone/test_phone_service.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from nose.tools import assert_true
 from datadiff.tools import assert_equal
 
diff --git a/Allura/allura/tests/unit/spam/test_akismet.py b/Allura/allura/tests/unit/spam/test_akismet.py
index b8a0315..c69eb51 100644
--- a/Allura/allura/tests/unit/spam/test_akismet.py
+++ b/Allura/allura/tests/unit/spam/test_akismet.py
@@ -19,6 +19,7 @@
 
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import mock
 import unittest
 import urllib
diff --git a/Allura/allura/tests/unit/spam/test_spam_filter.py b/Allura/allura/tests/unit/spam/test_spam_filter.py
index 2770121..ae1f9db 100644
--- a/Allura/allura/tests/unit/spam/test_spam_filter.py
+++ b/Allura/allura/tests/unit/spam/test_spam_filter.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import mock
 import unittest
 
diff --git a/Allura/allura/tests/unit/spam/test_stopforumspam.py b/Allura/allura/tests/unit/spam/test_stopforumspam.py
index b0d15f8..30f5202 100644
--- a/Allura/allura/tests/unit/spam/test_stopforumspam.py
+++ b/Allura/allura/tests/unit/spam/test_stopforumspam.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import tempfile
 
 import mock
diff --git a/Allura/allura/tests/unit/test_app.py b/Allura/allura/tests/unit/test_app.py
index 719f125..8ff7df9 100644
--- a/Allura/allura/tests/unit/test_app.py
+++ b/Allura/allura/tests/unit/test_app.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from unittest import TestCase
 
 from nose.tools import assert_equal
diff --git a/Allura/allura/tests/unit/test_artifact.py b/Allura/allura/tests/unit/test_artifact.py
index 1337b38..5d0cb99 100644
--- a/Allura/allura/tests/unit/test_artifact.py
+++ b/Allura/allura/tests/unit/test_artifact.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import unittest
 
 from allura import model as M
diff --git a/Allura/allura/tests/unit/test_discuss.py b/Allura/allura/tests/unit/test_discuss.py
index 665240f..8f227f0 100644
--- a/Allura/allura/tests/unit/test_discuss.py
+++ b/Allura/allura/tests/unit/test_discuss.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from nose.tools import assert_false, assert_true
 
 from allura import model as M
diff --git a/Allura/allura/tests/unit/test_helpers/test_ago.py b/Allura/allura/tests/unit/test_helpers/test_ago.py
index f89c6aa..ea09bdf 100644
--- a/Allura/allura/tests/unit/test_helpers/test_ago.py
+++ b/Allura/allura/tests/unit/test_helpers/test_ago.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from datetime import datetime
 
 from mock import patch
diff --git a/Allura/allura/tests/unit/test_helpers/test_set_context.py b/Allura/allura/tests/unit/test_helpers/test_set_context.py
index ba29a32..8f381ac 100644
--- a/Allura/allura/tests/unit/test_helpers/test_set_context.py
+++ b/Allura/allura/tests/unit/test_helpers/test_set_context.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from nose.tools import assert_raises
 from tg import tmpl_context as c
 from bson import ObjectId
diff --git a/Allura/allura/tests/unit/test_ldap_auth_provider.py b/Allura/allura/tests/unit/test_ldap_auth_provider.py
index 69865dc..4ced1ab 100644
--- a/Allura/allura/tests/unit/test_ldap_auth_provider.py
+++ b/Allura/allura/tests/unit/test_ldap_auth_provider.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import calendar
 import platform
 from datetime import datetime, timedelta
diff --git a/Allura/allura/tests/unit/test_mixins.py b/Allura/allura/tests/unit/test_mixins.py
index a29d013..76fecc4 100644
--- a/Allura/allura/tests/unit/test_mixins.py
+++ b/Allura/allura/tests/unit/test_mixins.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from mock import Mock
 from allura.model import VotableArtifact
 
diff --git a/Allura/allura/tests/unit/test_package_path_loader.py b/Allura/allura/tests/unit/test_package_path_loader.py
index 2422aab..56edd43 100644
--- a/Allura/allura/tests/unit/test_package_path_loader.py
+++ b/Allura/allura/tests/unit/test_package_path_loader.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from unittest import TestCase
 
 import jinja2
diff --git a/Allura/allura/tests/unit/test_post_model.py b/Allura/allura/tests/unit/test_post_model.py
index 031168a..838989e 100644
--- a/Allura/allura/tests/unit/test_post_model.py
+++ b/Allura/allura/tests/unit/test_post_model.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 
 from allura.lib import helpers as h
diff --git a/Allura/allura/tests/unit/test_project.py b/Allura/allura/tests/unit/test_project.py
index 4eaef6c..d2b66b7 100644
--- a/Allura/allura/tests/unit/test_project.py
+++ b/Allura/allura/tests/unit/test_project.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import unittest
 from mock import Mock
 
diff --git a/Allura/allura/tests/unit/test_repo.py b/Allura/allura/tests/unit/test_repo.py
index 792d5e5..7a4f3d9 100644
--- a/Allura/allura/tests/unit/test_repo.py
+++ b/Allura/allura/tests/unit/test_repo.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import datetime
 import unittest
 
diff --git a/Allura/allura/tests/unit/test_session.py b/Allura/allura/tests/unit/test_session.py
index 3d8ce08..3be5484 100644
--- a/Allura/allura/tests/unit/test_session.py
+++ b/Allura/allura/tests/unit/test_session.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import pymongo
 import mock
 
diff --git a/Allura/allura/tests/unit/test_sitemapentry.py b/Allura/allura/tests/unit/test_sitemapentry.py
index af294f5..e2a613d 100644
--- a/Allura/allura/tests/unit/test_sitemapentry.py
+++ b/Allura/allura/tests/unit/test_sitemapentry.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import unittest
 from mock import Mock
 
diff --git a/Allura/allura/tests/unit/test_solr.py b/Allura/allura/tests/unit/test_solr.py
index e1fdcf0..f568abf 100644
--- a/Allura/allura/tests/unit/test_solr.py
+++ b/Allura/allura/tests/unit/test_solr.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import unittest
 
 import mock
diff --git a/Allura/allura/webhooks.py b/Allura/allura/webhooks.py
index 6bee064..4c8447f 100644
--- a/Allura/allura/webhooks.py
+++ b/Allura/allura/webhooks.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import json
 import hmac
diff --git a/Allura/allura/websetup/__init__.py b/Allura/allura/websetup/__init__.py
index 1d5a386..cab8e31 100644
--- a/Allura/allura/websetup/__init__.py
+++ b/Allura/allura/websetup/__init__.py
@@ -20,6 +20,7 @@
 """Setup the allura application"""
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 from allura.config.environment import load_environment
@@ -28,8 +29,8 @@ __all__ = ['setup_app']
 
 log = logging.getLogger(__name__)
 
-from schema import setup_schema
-import bootstrap
+from .schema import setup_schema
+from . import bootstrap
 
 
 def setup_app(command, conf, vars):
diff --git a/Allura/allura/websetup/bootstrap.py b/Allura/allura/websetup/bootstrap.py
index 80bfe16..fc5b703 100644
--- a/Allura/allura/websetup/bootstrap.py
+++ b/Allura/allura/websetup/bootstrap.py
@@ -19,6 +19,7 @@
 
 """Setup the allura application"""
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import sys
 import logging
diff --git a/Allura/allura/websetup/schema.py b/Allura/allura/websetup/schema.py
index 3d4df41..f78034d 100644
--- a/Allura/allura/websetup/schema.py
+++ b/Allura/allura/websetup/schema.py
@@ -20,6 +20,7 @@
 """Setup the allura application"""
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 import activitystream
diff --git a/Allura/docs/conf.py b/Allura/docs/conf.py
index 99ced2c..2d6f439 100644
--- a/Allura/docs/conf.py
+++ b/Allura/docs/conf.py
@@ -38,6 +38,7 @@
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 
 extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx',
diff --git a/Allura/ldap-setup.py b/Allura/ldap-setup.py
index b8b3cb7..8ff17c4 100644
--- a/Allura/ldap-setup.py
+++ b/Allura/ldap-setup.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import shutil
 import string
diff --git a/Allura/ldap-userconfig.py b/Allura/ldap-userconfig.py
index 9f37660..63334b5 100644
--- a/Allura/ldap-userconfig.py
+++ b/Allura/ldap-userconfig.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import sys
 import pwd
diff --git a/Allura/setup.py b/Allura/setup.py
index 5abbc6e..441d51a 100644
--- a/Allura/setup.py
+++ b/Allura/setup.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from setuptools import setup, find_packages
 
 exec open('allura/version.py').read()
diff --git a/AlluraTest/alluratest/controller.py b/AlluraTest/alluratest/controller.py
index 5273060..bb7fd89 100644
--- a/AlluraTest/alluratest/controller.py
+++ b/AlluraTest/alluratest/controller.py
@@ -17,6 +17,7 @@
 
 """Unit and functional test suite for allura."""
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import urllib
 import json
diff --git a/AlluraTest/alluratest/pylint_checkers.py b/AlluraTest/alluratest/pylint_checkers.py
index 7442aeb..b1a7439 100644
--- a/AlluraTest/alluratest/pylint_checkers.py
+++ b/AlluraTest/alluratest/pylint_checkers.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import astroid
 
 from pylint.checkers import BaseChecker, utils
diff --git a/AlluraTest/alluratest/smtp_debug.py b/AlluraTest/alluratest/smtp_debug.py
index 5c9f037..301c164 100644
--- a/AlluraTest/alluratest/smtp_debug.py
+++ b/AlluraTest/alluratest/smtp_debug.py
@@ -19,6 +19,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 from smtpd import DebuggingServer
 
 
diff --git a/AlluraTest/alluratest/test_syntax.py b/AlluraTest/alluratest/test_syntax.py
index a6f5fff..6e71ebc 100644
--- a/AlluraTest/alluratest/test_syntax.py
+++ b/AlluraTest/alluratest/test_syntax.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os.path
 from subprocess import Popen, PIPE
 import sys
diff --git a/AlluraTest/alluratest/validation.py b/AlluraTest/alluratest/validation.py
index a6bf827..2ad3821 100644
--- a/AlluraTest/alluratest/validation.py
+++ b/AlluraTest/alluratest/validation.py
@@ -21,6 +21,7 @@
 Functions to syntax-validate output content
 """
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from os import path
 import os
 import sys
diff --git a/AlluraTest/setup.py b/AlluraTest/setup.py
index 9286f8b..b9e4f07 100644
--- a/AlluraTest/setup.py
+++ b/AlluraTest/setup.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from setuptools import setup, find_packages
 
 setup(name='AlluraTest',
diff --git a/ForgeActivity/forgeactivity/__init__.py b/ForgeActivity/forgeactivity/__init__.py
index d994a08..b3c6f5d 100644
--- a/ForgeActivity/forgeactivity/__init__.py
+++ b/ForgeActivity/forgeactivity/__init__.py
@@ -15,4 +15,5 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
-from main import ForgeActivityApp
+from __future__ import absolute_import
+from .main import ForgeActivityApp
diff --git a/ForgeActivity/forgeactivity/config/resources.py b/ForgeActivity/forgeactivity/config/resources.py
index 7370f46..faab364 100644
--- a/ForgeActivity/forgeactivity/config/resources.py
+++ b/ForgeActivity/forgeactivity/config/resources.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import pkg_resources
 
 
diff --git a/ForgeActivity/forgeactivity/main.py b/ForgeActivity/forgeactivity/main.py
index 33ce2e1..4888fa7 100644
--- a/ForgeActivity/forgeactivity/main.py
+++ b/ForgeActivity/forgeactivity/main.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import calendar
 from datetime import timedelta
diff --git a/ForgeActivity/forgeactivity/tests/functional/test_rest.py b/ForgeActivity/forgeactivity/tests/functional/test_rest.py
index 257b8b7..31d0dfd 100644
--- a/ForgeActivity/forgeactivity/tests/functional/test_rest.py
+++ b/ForgeActivity/forgeactivity/tests/functional/test_rest.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from datadiff.tools import assert_equal
 
 from tg import config
diff --git a/ForgeActivity/forgeactivity/tests/functional/test_root.py b/ForgeActivity/forgeactivity/tests/functional/test_root.py
index 751f515..7567004 100644
--- a/ForgeActivity/forgeactivity/tests/functional/test_root.py
+++ b/ForgeActivity/forgeactivity/tests/functional/test_root.py
@@ -17,6 +17,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from textwrap import dedent
 
 from mock import patch
diff --git a/ForgeActivity/forgeactivity/widgets/follow.py b/ForgeActivity/forgeactivity/widgets/follow.py
index 907c125..7d6bbf3 100644
--- a/ForgeActivity/forgeactivity/widgets/follow.py
+++ b/ForgeActivity/forgeactivity/widgets/follow.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 from formencode import validators as fev
 import ew as ew_core
diff --git a/ForgeActivity/setup.py b/ForgeActivity/setup.py
index 82db329..da41645 100644
--- a/ForgeActivity/setup.py
+++ b/ForgeActivity/setup.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from setuptools import setup, find_packages
 
 setup(name='ForgeActivity',
diff --git a/ForgeBlog/forgeblog/command/base.py b/ForgeBlog/forgeblog/command/base.py
index 4bcc0fa..98ffa26 100644
--- a/ForgeBlog/forgeblog/command/base.py
+++ b/ForgeBlog/forgeblog/command/base.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from allura.command.base import Command
 
 
diff --git a/ForgeBlog/forgeblog/command/rssfeeds.py b/ForgeBlog/forgeblog/command/rssfeeds.py
index 49cb12b..fa6e04e 100644
--- a/ForgeBlog/forgeblog/command/rssfeeds.py
+++ b/ForgeBlog/forgeblog/command/rssfeeds.py
@@ -16,13 +16,14 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import calendar
 from datetime import datetime
 
 import feedparser
 from bson import ObjectId
 
-import base
+from . import base
 from allura.command import base as allura_base
 
 from ming.orm import session
diff --git a/ForgeBlog/forgeblog/main.py b/ForgeBlog/forgeblog/main.py
index e04530d..79716af 100644
--- a/ForgeBlog/forgeblog/main.py
+++ b/ForgeBlog/forgeblog/main.py
@@ -17,6 +17,7 @@
 
 #-*- python -*-
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import urllib2
 import json
diff --git a/ForgeBlog/forgeblog/model/__init__.py b/ForgeBlog/forgeblog/model/__init__.py
index e1b5fcc..865bab1 100644
--- a/ForgeBlog/forgeblog/model/__init__.py
+++ b/ForgeBlog/forgeblog/model/__init__.py
@@ -15,4 +15,5 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
-from blog import Globals, BlogPost, BlogAttachment, BlogPostSnapshot
+from __future__ import absolute_import
+from .blog import Globals, BlogPost, BlogAttachment, BlogPostSnapshot
diff --git a/ForgeBlog/forgeblog/model/blog.py b/ForgeBlog/forgeblog/model/blog.py
index 83e8161..2583ba9 100644
--- a/ForgeBlog/forgeblog/model/blog.py
+++ b/ForgeBlog/forgeblog/model/blog.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import difflib
 import functools
 import re
diff --git a/ForgeBlog/forgeblog/tests/functional/test_feeds.py b/ForgeBlog/forgeblog/tests/functional/test_feeds.py
index 5ea699f..2608ea8 100644
--- a/ForgeBlog/forgeblog/tests/functional/test_feeds.py
+++ b/ForgeBlog/forgeblog/tests/functional/test_feeds.py
@@ -18,6 +18,7 @@
 
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import datetime
 
 from nose.tools import assert_in, assert_not_in
diff --git a/ForgeBlog/forgeblog/tests/functional/test_rest.py b/ForgeBlog/forgeblog/tests/functional/test_rest.py
index b38018b..826a0ed 100644
--- a/ForgeBlog/forgeblog/tests/functional/test_rest.py
+++ b/ForgeBlog/forgeblog/tests/functional/test_rest.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from datetime import date
 
 import tg
diff --git a/ForgeBlog/forgeblog/tests/functional/test_root.py b/ForgeBlog/forgeblog/tests/functional/test_root.py
index c893532..4358a98 100644
--- a/ForgeBlog/forgeblog/tests/functional/test_root.py
+++ b/ForgeBlog/forgeblog/tests/functional/test_root.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import datetime
 import json
 
diff --git a/ForgeBlog/forgeblog/tests/test_app.py b/ForgeBlog/forgeblog/tests/test_app.py
index d03460c..9f32613 100644
--- a/ForgeBlog/forgeblog/tests/test_app.py
+++ b/ForgeBlog/forgeblog/tests/test_app.py
@@ -18,6 +18,7 @@
 #-*- python -*-
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import tempfile
 import json
 import os
diff --git a/ForgeBlog/forgeblog/tests/test_commands.py b/ForgeBlog/forgeblog/tests/test_commands.py
index b7531ec..f728ca4 100644
--- a/ForgeBlog/forgeblog/tests/test_commands.py
+++ b/ForgeBlog/forgeblog/tests/test_commands.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from datetime import datetime, timedelta
 from tg import app_globals as g
 from datadiff.tools import assert_equal
diff --git a/ForgeBlog/forgeblog/tests/test_roles.py b/ForgeBlog/forgeblog/tests/test_roles.py
index 13b82e7..78eb5a5 100644
--- a/ForgeBlog/forgeblog/tests/test_roles.py
+++ b/ForgeBlog/forgeblog/tests/test_roles.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c, app_globals as g
 
 from alluratest.controller import setup_basic_test, setup_global_objects
diff --git a/ForgeBlog/forgeblog/tests/unit/__init__.py b/ForgeBlog/forgeblog/tests/unit/__init__.py
index b42e51b..d8d75fc 100644
--- a/ForgeBlog/forgeblog/tests/unit/__init__.py
+++ b/ForgeBlog/forgeblog/tests/unit/__init__.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 from ming.orm.ormsession import ThreadLocalORMSession
 
diff --git a/ForgeBlog/forgeblog/tests/unit/test_blog_post.py b/ForgeBlog/forgeblog/tests/unit/test_blog_post.py
index 69e3a6d..f4b7b58 100644
--- a/ForgeBlog/forgeblog/tests/unit/test_blog_post.py
+++ b/ForgeBlog/forgeblog/tests/unit/test_blog_post.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from datetime import datetime
 from nose.tools import assert_equal, assert_true
 from tg import tmpl_context as c
diff --git a/ForgeBlog/forgeblog/widgets.py b/ForgeBlog/forgeblog/widgets.py
index 1255553..3d52bc5 100644
--- a/ForgeBlog/forgeblog/widgets.py
+++ b/ForgeBlog/forgeblog/widgets.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import ew as ew_core
 import ew.jinja2_ew as ew
 
diff --git a/ForgeBlog/setup.py b/ForgeBlog/setup.py
index df75380..0670242 100644
--- a/ForgeBlog/setup.py
+++ b/ForgeBlog/setup.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from setuptools import setup, find_packages
 
 from forgeblog.version import __version__
diff --git a/ForgeChat/forgechat/command.py b/ForgeChat/forgechat/command.py
index b82cc05..a1a0806 100644
--- a/ForgeChat/forgechat/command.py
+++ b/ForgeChat/forgechat/command.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import time
 import logging
 import socket
diff --git a/ForgeChat/forgechat/main.py b/ForgeChat/forgechat/main.py
index 3b65b68..4c7a43c 100644
--- a/ForgeChat/forgechat/main.py
+++ b/ForgeChat/forgechat/main.py
@@ -19,6 +19,7 @@
 '''
 #-*- python -*-
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from datetime import date, time, datetime, timedelta
 
diff --git a/ForgeChat/forgechat/model/__init__.py b/ForgeChat/forgechat/model/__init__.py
index cf46080..a519366 100644
--- a/ForgeChat/forgechat/model/__init__.py
+++ b/ForgeChat/forgechat/model/__init__.py
@@ -15,4 +15,5 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
-from chat import ChatChannel, ChatMessage
+from __future__ import absolute_import
+from .chat import ChatChannel, ChatMessage
diff --git a/ForgeChat/forgechat/model/chat.py b/ForgeChat/forgechat/model/chat.py
index e444438..a2079fe 100644
--- a/ForgeChat/forgechat/model/chat.py
+++ b/ForgeChat/forgechat/model/chat.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from datetime import datetime
 
 from ming import schema as S
diff --git a/ForgeChat/forgechat/tests/functional/test_root.py b/ForgeChat/forgechat/tests/functional/test_root.py
index 1ea95af..8e58f62 100644
--- a/ForgeChat/forgechat/tests/functional/test_root.py
+++ b/ForgeChat/forgechat/tests/functional/test_root.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 from datadiff.tools import assert_equal
 
diff --git a/ForgeChat/setup.py b/ForgeChat/setup.py
index b326d14..71c455e 100644
--- a/ForgeChat/setup.py
+++ b/ForgeChat/setup.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from setuptools import setup, find_packages
 
 from forgechat.version import __version__
diff --git a/ForgeDiscussion/forgediscussion/controllers/__init__.py b/ForgeDiscussion/forgediscussion/controllers/__init__.py
index e146302..2dd782d 100644
--- a/ForgeDiscussion/forgediscussion/controllers/__init__.py
+++ b/ForgeDiscussion/forgediscussion/controllers/__init__.py
@@ -15,4 +15,5 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
-from root import RootController, RootRestController
+from __future__ import absolute_import
+from .root import RootController, RootRestController
diff --git a/ForgeDiscussion/forgediscussion/controllers/forum.py b/ForgeDiscussion/forgediscussion/controllers/forum.py
index c427d68..cf0b1f2 100644
--- a/ForgeDiscussion/forgediscussion/controllers/forum.py
+++ b/ForgeDiscussion/forgediscussion/controllers/forum.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import re
 
diff --git a/ForgeDiscussion/forgediscussion/controllers/root.py b/ForgeDiscussion/forgediscussion/controllers/root.py
index 9102ebb..5653b76 100644
--- a/ForgeDiscussion/forgediscussion/controllers/root.py
+++ b/ForgeDiscussion/forgediscussion/controllers/root.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 import logging
 from urllib import unquote
diff --git a/ForgeDiscussion/forgediscussion/forum_main.py b/ForgeDiscussion/forgediscussion/forum_main.py
index c7b3d4d..a1ccdab 100644
--- a/ForgeDiscussion/forgediscussion/forum_main.py
+++ b/ForgeDiscussion/forgediscussion/forum_main.py
@@ -17,6 +17,7 @@
 
 #-*- python -*-
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import urllib
 import json
@@ -44,7 +45,7 @@ from forgediscussion import utils
 from forgediscussion import version
 from .controllers import RootController, RootRestController
 
-from widgets.admin import OptionsAdmin, AddForum
+from .widgets.admin import OptionsAdmin, AddForum
 
 
 log = logging.getLogger(__name__)
diff --git a/ForgeDiscussion/forgediscussion/import_support.py b/ForgeDiscussion/forgediscussion/import_support.py
index d31b3a1..f1040f6 100644
--- a/ForgeDiscussion/forgediscussion/import_support.py
+++ b/ForgeDiscussion/forgediscussion/import_support.py
@@ -17,6 +17,7 @@
 
 #-*- python -*-
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from datetime import datetime
 
diff --git a/ForgeDiscussion/forgediscussion/model/__init__.py b/ForgeDiscussion/forgediscussion/model/__init__.py
index 63a2171..e66e25f 100644
--- a/ForgeDiscussion/forgediscussion/model/__init__.py
+++ b/ForgeDiscussion/forgediscussion/model/__init__.py
@@ -15,4 +15,5 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
-from forum import Forum, ForumThread, ForumPost, ForumAttachment
+from __future__ import absolute_import
+from .forum import Forum, ForumThread, ForumPost, ForumAttachment
diff --git a/ForgeDiscussion/forgediscussion/model/forum.py b/ForgeDiscussion/forgediscussion/model/forum.py
index 1916f55..30440f2 100644
--- a/ForgeDiscussion/forgediscussion/model/forum.py
+++ b/ForgeDiscussion/forgediscussion/model/forum.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 import logging
 from itertools import chain
diff --git a/ForgeDiscussion/forgediscussion/site_stats.py b/ForgeDiscussion/forgediscussion/site_stats.py
index 53fef07..7713049 100644
--- a/ForgeDiscussion/forgediscussion/site_stats.py
+++ b/ForgeDiscussion/forgediscussion/site_stats.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from datetime import datetime, timedelta
 
 from . import model as DM
diff --git a/ForgeDiscussion/forgediscussion/tasks.py b/ForgeDiscussion/forgediscussion/tasks.py
index 265a0db..18e3eb1 100644
--- a/ForgeDiscussion/forgediscussion/tasks.py
+++ b/ForgeDiscussion/forgediscussion/tasks.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 from tg import tmpl_context as c
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
index 0b7a7c0..4a6f38b 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import mock
 import random
 import logging
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py b/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
index 8f5a337..41682ec 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import allura
 from StringIO import StringIO
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_import.py b/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
index 5167448..c95cf35 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import json
 from datetime import datetime, timedelta
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py b/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
index bca2e08..f07c1a3 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from nose.tools import assert_equal, assert_in
 
 from allura.lib import helpers as h
diff --git a/ForgeDiscussion/forgediscussion/tests/test_app.py b/ForgeDiscussion/forgediscussion/tests/test_app.py
index d7493d1..4e842c3 100644
--- a/ForgeDiscussion/forgediscussion/tests/test_app.py
+++ b/ForgeDiscussion/forgediscussion/tests/test_app.py
@@ -20,6 +20,7 @@
 #-*- python -*-
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import tempfile
 import json
 import os
diff --git a/ForgeDiscussion/forgediscussion/tests/test_forum_roles.py b/ForgeDiscussion/forgediscussion/tests/test_forum_roles.py
index 7e688f1..73fcae7 100644
--- a/ForgeDiscussion/forgediscussion/tests/test_forum_roles.py
+++ b/ForgeDiscussion/forgediscussion/tests/test_forum_roles.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 
 from alluratest.controller import setup_basic_test, setup_global_objects
diff --git a/ForgeDiscussion/forgediscussion/utils.py b/ForgeDiscussion/forgediscussion/utils.py
index 76cd473..ba635cc 100644
--- a/ForgeDiscussion/forgediscussion/utils.py
+++ b/ForgeDiscussion/forgediscussion/utils.py
@@ -18,6 +18,7 @@
 """ ForgeDiscussion utilities. """
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from bson import ObjectId
 from tg import flash
 from allura.lib import helpers as h
diff --git a/ForgeDiscussion/forgediscussion/widgets/__init__.py b/ForgeDiscussion/forgediscussion/widgets/__init__.py
index cbe2c73..8e1c918 100644
--- a/ForgeDiscussion/forgediscussion/widgets/__init__.py
+++ b/ForgeDiscussion/forgediscussion/widgets/__init__.py
@@ -16,9 +16,10 @@
 #       under the License.
 
 from __future__ import unicode_literals
-from forum_widgets import ThreadSubscriptionForm, AnnouncementsTable
-from forum_widgets import ModerateThread, ForumHeader, ThreadHeader
-from forum_widgets import Post, Thread, Forum
+from __future__ import absolute_import
+from .forum_widgets import ThreadSubscriptionForm, AnnouncementsTable
+from .forum_widgets import ModerateThread, ForumHeader, ThreadHeader
+from .forum_widgets import Post, Thread, Forum
 
 __all__ = [
     'ThreadSubscriptionForm', 'AnnouncementsTable', 'ModerateThread', 'ForumHeader',
diff --git a/ForgeDiscussion/forgediscussion/widgets/admin.py b/ForgeDiscussion/forgediscussion/widgets/admin.py
index af1d079..cec8eda 100644
--- a/ForgeDiscussion/forgediscussion/widgets/admin.py
+++ b/ForgeDiscussion/forgediscussion/widgets/admin.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from formencode import validators as fev
 from formencode import All
 import formencode
diff --git a/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py b/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py
index 7707e5c..9355fe6 100644
--- a/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py
+++ b/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 from formencode import validators as fev
 
diff --git a/ForgeDiscussion/setup.py b/ForgeDiscussion/setup.py
index f6a12f8..d0007d5 100644
--- a/ForgeDiscussion/setup.py
+++ b/ForgeDiscussion/setup.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from setuptools import setup, find_packages
 
 from forgediscussion.version import __version__
diff --git a/ForgeFeedback/forgefeedback/feedback_main.py b/ForgeFeedback/forgefeedback/feedback_main.py
index bd02001..aee8ea8 100755
--- a/ForgeFeedback/forgefeedback/feedback_main.py
+++ b/ForgeFeedback/forgefeedback/feedback_main.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import pymongo
 
diff --git a/ForgeFeedback/forgefeedback/model/__init__.py b/ForgeFeedback/forgefeedback/model/__init__.py
index fc61e16..0a2340e 100755
--- a/ForgeFeedback/forgefeedback/model/__init__.py
+++ b/ForgeFeedback/forgefeedback/model/__init__.py
@@ -15,4 +15,5 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
-from feedback import Feedback
+from __future__ import absolute_import
+from .feedback import Feedback
diff --git a/ForgeFeedback/forgefeedback/model/feedback.py b/ForgeFeedback/forgefeedback/model/feedback.py
index 0dc78a2..28b4948 100755
--- a/ForgeFeedback/forgefeedback/model/feedback.py
+++ b/ForgeFeedback/forgefeedback/model/feedback.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import urllib
 # Non-stdlib imports
diff --git a/ForgeFeedback/forgefeedback/tests/functional/test_root.py b/ForgeFeedback/forgefeedback/tests/functional/test_root.py
index 45113d8..ab9852b 100755
--- a/ForgeFeedback/forgefeedback/tests/functional/test_root.py
+++ b/ForgeFeedback/forgefeedback/tests/functional/test_root.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 from tg import config
 
diff --git a/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py b/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py
index 11c1e72..e7ebe07 100755
--- a/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py
+++ b/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c, app_globals as g
 
 from nose.tools import assert_equal
diff --git a/ForgeFeedback/forgefeedback/tests/unit/__init__.py b/ForgeFeedback/forgefeedback/tests/unit/__init__.py
index 91e95d4..b2512e0 100755
--- a/ForgeFeedback/forgefeedback/tests/unit/__init__.py
+++ b/ForgeFeedback/forgefeedback/tests/unit/__init__.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 from ming.orm.ormsession import ThreadLocalORMSession
 
diff --git a/ForgeFeedback/forgefeedback/tests/unit/test_feedback.py b/ForgeFeedback/forgefeedback/tests/unit/test_feedback.py
index b7e4154..440e124 100755
--- a/ForgeFeedback/forgefeedback/tests/unit/test_feedback.py
+++ b/ForgeFeedback/forgefeedback/tests/unit/test_feedback.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from datetime import datetime
 from nose.tools import assert_equal, assert_true
 from tg import tmpl_context as c
diff --git a/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py b/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py
index 3acfaa8..9786960 100755
--- a/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py
+++ b/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import unittest
 
 from mock import Mock, patch
diff --git a/ForgeFeedback/setup.py b/ForgeFeedback/setup.py
index 0edfbb2..02f25b2 100755
--- a/ForgeFeedback/setup.py
+++ b/ForgeFeedback/setup.py
@@ -17,6 +17,7 @@
 
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from setuptools import setup, find_packages
 
 from forgefeedback.version import __version__
diff --git a/ForgeGit/forgegit/controllers.py b/ForgeGit/forgegit/controllers.py
index 9164b28..188f8c4 100644
--- a/ForgeGit/forgegit/controllers.py
+++ b/ForgeGit/forgegit/controllers.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import expose, redirect
 from tg.decorators import with_trailing_slash
 from tg import tmpl_context as c
diff --git a/ForgeGit/forgegit/git_main.py b/ForgeGit/forgegit/git_main.py
index 455efa7..f6d5d5b 100644
--- a/ForgeGit/forgegit/git_main.py
+++ b/ForgeGit/forgegit/git_main.py
@@ -17,6 +17,7 @@
 
 #-*- python -*-
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 # Non-stdlib imports
diff --git a/ForgeGit/forgegit/model/__init__.py b/ForgeGit/forgegit/model/__init__.py
index 72eb80a..315be3b 100644
--- a/ForgeGit/forgegit/model/__init__.py
+++ b/ForgeGit/forgegit/model/__init__.py
@@ -15,4 +15,5 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
-from git_repo import Repository
+from __future__ import absolute_import
+from .git_repo import Repository
diff --git a/ForgeGit/forgegit/model/git_repo.py b/ForgeGit/forgegit/model/git_repo.py
index 171c69a..cf829f4 100644
--- a/ForgeGit/forgegit/model/git_repo.py
+++ b/ForgeGit/forgegit/model/git_repo.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import shutil
 import string
diff --git a/ForgeGit/forgegit/tests/__init__.py b/ForgeGit/forgegit/tests/__init__.py
index 16153e2..1f51dcf 100644
--- a/ForgeGit/forgegit/tests/__init__.py
+++ b/ForgeGit/forgegit/tests/__init__.py
@@ -20,6 +20,7 @@
 
 # Make our own Git tool test decorator
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from allura.tests.decorators import with_tool
 
 with_git = with_tool('test', 'Git', 'src-git', 'Git', type='git')
diff --git a/ForgeGit/forgegit/tests/functional/test_auth.py b/ForgeGit/forgegit/tests/functional/test_auth.py
index ec0f980..8cffeac 100644
--- a/ForgeGit/forgegit/tests/functional/test_auth.py
+++ b/ForgeGit/forgegit/tests/functional/test_auth.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 from datadiff.tools import assert_equal
 
diff --git a/ForgeGit/forgegit/tests/functional/test_controllers.py b/ForgeGit/forgegit/tests/functional/test_controllers.py
index 89665e4..40ddef2 100644
--- a/ForgeGit/forgegit/tests/functional/test_controllers.py
+++ b/ForgeGit/forgegit/tests/functional/test_controllers.py
@@ -19,6 +19,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import json
 import re
 import os
diff --git a/ForgeGit/forgegit/tests/model/test_repository.py b/ForgeGit/forgegit/tests/model/test_repository.py
index df7d91e..a80d9b8 100644
--- a/ForgeGit/forgegit/tests/model/test_repository.py
+++ b/ForgeGit/forgegit/tests/model/test_repository.py
@@ -19,6 +19,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import os
 import shutil
 import stat
diff --git a/ForgeGit/forgegit/tests/test_git_app.py b/ForgeGit/forgegit/tests/test_git_app.py
index b43aac5..f8e850f 100644
--- a/ForgeGit/forgegit/tests/test_git_app.py
+++ b/ForgeGit/forgegit/tests/test_git_app.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import unittest
 from nose.tools import assert_equals
 
diff --git a/ForgeGit/forgegit/tests/test_tasks.py b/ForgeGit/forgegit/tests/test_tasks.py
index 37248f0..9eb9c35 100644
--- a/ForgeGit/forgegit/tests/test_tasks.py
+++ b/ForgeGit/forgegit/tests/test_tasks.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import unittest
 import mock
 from testfixtures import LogCapture
diff --git a/ForgeGit/setup.py b/ForgeGit/setup.py
index 8ceb54b..8cadb33 100644
--- a/ForgeGit/setup.py
+++ b/ForgeGit/setup.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from setuptools import setup, find_packages
 
 from forgegit.version import __version__
diff --git a/ForgeImporters/forgeimporters/base.py b/ForgeImporters/forgeimporters/base.py
index 91d025e..1fd5d29 100644
--- a/ForgeImporters/forgeimporters/base.py
+++ b/ForgeImporters/forgeimporters/base.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import errno
 import logging
diff --git a/ForgeImporters/forgeimporters/forge/tracker.py b/ForgeImporters/forgeimporters/forge/tracker.py
index e7024c1..19638b1 100644
--- a/ForgeImporters/forgeimporters/forge/tracker.py
+++ b/ForgeImporters/forgeimporters/forge/tracker.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import json
 
diff --git a/ForgeImporters/forgeimporters/github/__init__.py b/ForgeImporters/forgeimporters/github/__init__.py
index ac538c5..c991127 100644
--- a/ForgeImporters/forgeimporters/github/__init__.py
+++ b/ForgeImporters/forgeimporters/github/__init__.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 import logging
 import json
diff --git a/ForgeImporters/forgeimporters/github/code.py b/ForgeImporters/forgeimporters/github/code.py
index ac53bce..8a4449e 100644
--- a/ForgeImporters/forgeimporters/github/code.py
+++ b/ForgeImporters/forgeimporters/github/code.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 from tg import app_globals as g
 from formencode import validators as fev
diff --git a/ForgeImporters/forgeimporters/github/project.py b/ForgeImporters/forgeimporters/github/project.py
index 7586971..914ccf8 100644
--- a/ForgeImporters/forgeimporters/github/project.py
+++ b/ForgeImporters/forgeimporters/github/project.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 from tg import expose, validate
diff --git a/ForgeImporters/forgeimporters/github/tasks.py b/ForgeImporters/forgeimporters/github/tasks.py
index a1cd9bb..5e04953 100644
--- a/ForgeImporters/forgeimporters/github/tasks.py
+++ b/ForgeImporters/forgeimporters/github/tasks.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 from tg import app_globals as g
 
diff --git a/ForgeImporters/forgeimporters/github/tests/test_code.py b/ForgeImporters/forgeimporters/github/tests/test_code.py
index 0f7bc09..cbb1e6e 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_code.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_code.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from unittest import TestCase
 from mock import Mock, patch
 from ming.odm import ThreadLocalORMSession
diff --git a/ForgeImporters/forgeimporters/github/tests/test_oauth.py b/ForgeImporters/forgeimporters/github/tests/test_oauth.py
index ddbe89b..7e60b7e 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_oauth.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_oauth.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from unittest import TestCase
 
 from mock import Mock, patch, MagicMock
diff --git a/ForgeImporters/forgeimporters/github/tests/test_tracker.py b/ForgeImporters/forgeimporters/github/tests/test_tracker.py
index a25ccd5..0707ef9 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_tracker.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_tracker.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from unittest import TestCase
 from mock import patch
 from ming.odm import ThreadLocalORMSession
diff --git a/ForgeImporters/forgeimporters/github/tests/test_utils.py b/ForgeImporters/forgeimporters/github/tests/test_utils.py
index 0f482a2..86d8763 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_utils.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_utils.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from nose.tools import assert_equal
 
 from forgeimporters.github.utils import GitHubMarkdownConverter
diff --git a/ForgeImporters/forgeimporters/github/tests/test_wiki.py b/ForgeImporters/forgeimporters/github/tests/test_wiki.py
index 8f21f55..cdbcb19 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_wiki.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_wiki.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from unittest import TestCase
 from nose.tools import assert_equal
 from mock import Mock, patch, call
diff --git a/ForgeImporters/forgeimporters/github/tracker.py b/ForgeImporters/forgeimporters/github/tracker.py
index 23c3fff..1153eb1 100644
--- a/ForgeImporters/forgeimporters/github/tracker.py
+++ b/ForgeImporters/forgeimporters/github/tracker.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 import logging
 from datetime import datetime
diff --git a/ForgeImporters/forgeimporters/github/utils.py b/ForgeImporters/forgeimporters/github/utils.py
index edecb1b..23cb010 100644
--- a/ForgeImporters/forgeimporters/github/utils.py
+++ b/ForgeImporters/forgeimporters/github/utils.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 
 
diff --git a/ForgeImporters/forgeimporters/github/wiki.py b/ForgeImporters/forgeimporters/github/wiki.py
index b1f7a38..9a0839b 100644
--- a/ForgeImporters/forgeimporters/github/wiki.py
+++ b/ForgeImporters/forgeimporters/github/wiki.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import os
 import re
 from datetime import datetime
diff --git a/ForgeImporters/forgeimporters/tests/forge/test_tracker.py b/ForgeImporters/forgeimporters/tests/forge/test_tracker.py
index e56c5e4..1e094ab 100644
--- a/ForgeImporters/forgeimporters/tests/forge/test_tracker.py
+++ b/ForgeImporters/forgeimporters/tests/forge/test_tracker.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from datetime import datetime
 from unittest import TestCase
 
diff --git a/ForgeImporters/forgeimporters/tests/github/functional/test_github.py b/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
index e1fa14a..1c0eb4d 100644
--- a/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
+++ b/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import requests
 import tg
 from mock import patch, call, Mock
diff --git a/ForgeImporters/forgeimporters/tests/github/test_extractor.py b/ForgeImporters/forgeimporters/tests/github/test_extractor.py
index f4106aa..ca5cd3b 100644
--- a/ForgeImporters/forgeimporters/tests/github/test_extractor.py
+++ b/ForgeImporters/forgeimporters/tests/github/test_extractor.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 from unittest import TestCase
 import urllib2
diff --git a/ForgeImporters/forgeimporters/tests/github/test_tasks.py b/ForgeImporters/forgeimporters/tests/github/test_tasks.py
index 98effbd..86b1a2f 100644
--- a/ForgeImporters/forgeimporters/tests/github/test_tasks.py
+++ b/ForgeImporters/forgeimporters/tests/github/test_tasks.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import mock
 
 from ...github import tasks
diff --git a/ForgeImporters/forgeimporters/tests/github/test_tracker.py b/ForgeImporters/forgeimporters/tests/github/test_tracker.py
index 47af12d..87cf96e 100644
--- a/ForgeImporters/forgeimporters/tests/github/test_tracker.py
+++ b/ForgeImporters/forgeimporters/tests/github/test_tracker.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from datetime import datetime
 from unittest import TestCase
 from urllib2 import HTTPError
diff --git a/ForgeImporters/forgeimporters/tests/test_base.py b/ForgeImporters/forgeimporters/tests/test_base.py
index 14a38b8..917bea5 100644
--- a/ForgeImporters/forgeimporters/tests/test_base.py
+++ b/ForgeImporters/forgeimporters/tests/test_base.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from unittest import TestCase
 import errno
 
diff --git a/ForgeImporters/forgeimporters/trac/__init__.py b/ForgeImporters/forgeimporters/trac/__init__.py
index dafc543..3a0949d 100644
--- a/ForgeImporters/forgeimporters/trac/__init__.py
+++ b/ForgeImporters/forgeimporters/trac/__init__.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from formencode import validators as fev
 import requests
 
diff --git a/ForgeImporters/forgeimporters/trac/project.py b/ForgeImporters/forgeimporters/trac/project.py
index 25c3f43..bd85763 100644
--- a/ForgeImporters/forgeimporters/trac/project.py
+++ b/ForgeImporters/forgeimporters/trac/project.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 from tg import expose, validate
diff --git a/ForgeImporters/forgeimporters/trac/tests/functional/test_trac.py b/ForgeImporters/forgeimporters/trac/tests/functional/test_trac.py
index babe127..bd9edfe 100644
--- a/ForgeImporters/forgeimporters/trac/tests/functional/test_trac.py
+++ b/ForgeImporters/forgeimporters/trac/tests/functional/test_trac.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from mock import patch, Mock
 from nose.tools import assert_equal
 from tg import config
diff --git a/ForgeImporters/forgeimporters/trac/tests/test_tickets.py b/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
index 210e2fe..bf3be44 100644
--- a/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
+++ b/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 import os
 
diff --git a/ForgeImporters/forgeimporters/trac/tickets.py b/ForgeImporters/forgeimporters/trac/tickets.py
index ebdc60a..a644ed2 100644
--- a/ForgeImporters/forgeimporters/trac/tickets.py
+++ b/ForgeImporters/forgeimporters/trac/tickets.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 import re
 
diff --git a/ForgeImporters/setup.py b/ForgeImporters/setup.py
index 21c9d91..adae23d 100644
--- a/ForgeImporters/setup.py
+++ b/ForgeImporters/setup.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from setuptools import setup, find_packages
 
 
diff --git a/ForgeLink/forgelink/link_main.py b/ForgeLink/forgelink/link_main.py
index acc13df..f314f65 100644
--- a/ForgeLink/forgelink/link_main.py
+++ b/ForgeLink/forgelink/link_main.py
@@ -17,6 +17,7 @@
 
 # -*- python -*-
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import json
 
diff --git a/ForgeLink/forgelink/tests/functional/test_rest.py b/ForgeLink/forgelink/tests/functional/test_rest.py
index ced7978..7d5c419 100644
--- a/ForgeLink/forgelink/tests/functional/test_rest.py
+++ b/ForgeLink/forgelink/tests/functional/test_rest.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from nose.tools import assert_equal
 from allura.tests import decorators as td
 from alluratest.controller import TestRestApiBase
diff --git a/ForgeLink/forgelink/tests/functional/test_root.py b/ForgeLink/forgelink/tests/functional/test_root.py
index ad82051..527178a 100644
--- a/ForgeLink/forgelink/tests/functional/test_root.py
+++ b/ForgeLink/forgelink/tests/functional/test_root.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 
 from nose.tools import assert_equal, assert_in
diff --git a/ForgeLink/forgelink/tests/test_app.py b/ForgeLink/forgelink/tests/test_app.py
index 4950f20..310a4d2 100644
--- a/ForgeLink/forgelink/tests/test_app.py
+++ b/ForgeLink/forgelink/tests/test_app.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import tempfile
 import json
 
diff --git a/ForgeLink/setup.py b/ForgeLink/setup.py
index 7e10d92..20e639d 100644
--- a/ForgeLink/setup.py
+++ b/ForgeLink/setup.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from setuptools import setup, find_packages
 
 from forgelink.version import __version__
diff --git a/ForgeSVN/forgesvn/controllers.py b/ForgeSVN/forgesvn/controllers.py
index b8cdbd6..1d967e4 100644
--- a/ForgeSVN/forgesvn/controllers.py
+++ b/ForgeSVN/forgesvn/controllers.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import expose, redirect
 from tg.decorators import with_trailing_slash
 from tg import tmpl_context as c
diff --git a/ForgeSVN/forgesvn/model/__init__.py b/ForgeSVN/forgesvn/model/__init__.py
index b19a8c6..f9d1766 100644
--- a/ForgeSVN/forgesvn/model/__init__.py
+++ b/ForgeSVN/forgesvn/model/__init__.py
@@ -15,4 +15,5 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
-from svn import Repository
+from __future__ import absolute_import
+from .svn import Repository
diff --git a/ForgeSVN/forgesvn/model/svn.py b/ForgeSVN/forgesvn/model/svn.py
index 4f7560a..d413ee8 100644
--- a/ForgeSVN/forgesvn/model/svn.py
+++ b/ForgeSVN/forgesvn/model/svn.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 import os
 import shutil
diff --git a/ForgeSVN/forgesvn/svn_main.py b/ForgeSVN/forgesvn/svn_main.py
index 24ee714..3b48259 100644
--- a/ForgeSVN/forgesvn/svn_main.py
+++ b/ForgeSVN/forgesvn/svn_main.py
@@ -17,6 +17,7 @@
 
 #-*- python -*-
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from tg import tmpl_context as c, request
 
diff --git a/ForgeSVN/forgesvn/tests/__init__.py b/ForgeSVN/forgesvn/tests/__init__.py
index 172a607..1592551 100644
--- a/ForgeSVN/forgesvn/tests/__init__.py
+++ b/ForgeSVN/forgesvn/tests/__init__.py
@@ -20,6 +20,7 @@
 
 # Make our own SVN tool test decorator
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from allura.tests.decorators import with_tool
 
 with_svn = with_tool('test', 'SVN', 'src', 'SVN')
diff --git a/ForgeSVN/forgesvn/tests/functional/test_auth.py b/ForgeSVN/forgesvn/tests/functional/test_auth.py
index b7b350a..e4b760c 100644
--- a/ForgeSVN/forgesvn/tests/functional/test_auth.py
+++ b/ForgeSVN/forgesvn/tests/functional/test_auth.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 from datadiff.tools import assert_equal
 
diff --git a/ForgeSVN/forgesvn/tests/functional/test_controllers.py b/ForgeSVN/forgesvn/tests/functional/test_controllers.py
index 079aa7e..97a1fb0 100644
--- a/ForgeSVN/forgesvn/tests/functional/test_controllers.py
+++ b/ForgeSVN/forgesvn/tests/functional/test_controllers.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 import shutil
 import os
diff --git a/ForgeSVN/forgesvn/tests/model/test_repository.py b/ForgeSVN/forgesvn/tests/model/test_repository.py
index 322bcd2..f00ecc1 100644
--- a/ForgeSVN/forgesvn/tests/model/test_repository.py
+++ b/ForgeSVN/forgesvn/tests/model/test_repository.py
@@ -18,6 +18,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import os
 import shutil
 import unittest
diff --git a/ForgeSVN/forgesvn/tests/model/test_svnimplementation.py b/ForgeSVN/forgesvn/tests/model/test_svnimplementation.py
index 9efaee7..ed599f2 100644
--- a/ForgeSVN/forgesvn/tests/model/test_svnimplementation.py
+++ b/ForgeSVN/forgesvn/tests/model/test_svnimplementation.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from mock import Mock, patch
 from nose.tools import assert_equal
 from tg import app_globals as g
diff --git a/ForgeSVN/forgesvn/tests/test_svn_app.py b/ForgeSVN/forgesvn/tests/test_svn_app.py
index a8d382b..49d945b 100644
--- a/ForgeSVN/forgesvn/tests/test_svn_app.py
+++ b/ForgeSVN/forgesvn/tests/test_svn_app.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import unittest
 from nose.tools import assert_equals
 
diff --git a/ForgeSVN/forgesvn/tests/test_tasks.py b/ForgeSVN/forgesvn/tests/test_tasks.py
index c041027..925f706 100644
--- a/ForgeSVN/forgesvn/tests/test_tasks.py
+++ b/ForgeSVN/forgesvn/tests/test_tasks.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import shutil
 import unittest
 import os
diff --git a/ForgeSVN/forgesvn/widgets.py b/ForgeSVN/forgesvn/widgets.py
index 591174c..69ce307 100644
--- a/ForgeSVN/forgesvn/widgets.py
+++ b/ForgeSVN/forgesvn/widgets.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 
 import ew as ew_core
diff --git a/ForgeSVN/setup.py b/ForgeSVN/setup.py
index c0409b7..dd8dd0e 100644
--- a/ForgeSVN/setup.py
+++ b/ForgeSVN/setup.py
@@ -17,6 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 from setuptools import setup, find_packages
 
 from forgesvn.version import __version__
diff --git a/ForgeShortUrl/forgeshorturl/main.py b/ForgeShortUrl/forgeshorturl/main.py
index db01bf5..290b6f7 100644
--- a/ForgeShortUrl/forgeshorturl/main.py
+++ b/ForgeShortUrl/forgeshorturl/main.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import expose, validate, redirect, flash, request
 from tg.decorators import without_trailing_slash
 
diff --git a/ForgeShortUrl/forgeshorturl/model/shorturl.py b/ForgeShortUrl/forgeshorturl/model/shorturl.py
index 98fecae..90aa038 100644
--- a/ForgeShortUrl/forgeshorturl/model/shorturl.py
+++ b/ForgeShortUrl/forgeshorturl/model/shorturl.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import pymongo
 from tg import config
 from tg import tmpl_context as c
diff --git a/ForgeShortUrl/forgeshorturl/tests/functional/test.py b/ForgeShortUrl/forgeshorturl/tests/functional/test.py
index a93ab53..18c0549 100644
--- a/ForgeShortUrl/forgeshorturl/tests/functional/test.py
+++ b/ForgeShortUrl/forgeshorturl/tests/functional/test.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 from tg import config
 from nose.tools import assert_equal
diff --git a/ForgeShortUrl/forgeshorturl/widgets/short_url.py b/ForgeShortUrl/forgeshorturl/widgets/short_url.py
index a17086e..f35e56a 100644
--- a/ForgeShortUrl/forgeshorturl/widgets/short_url.py
+++ b/ForgeShortUrl/forgeshorturl/widgets/short_url.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from allura.lib.widgets import form_fields as ffw
 
 
diff --git a/ForgeShortUrl/setup.py b/ForgeShortUrl/setup.py
index 61a618b..de4c9b2 100644
--- a/ForgeShortUrl/setup.py
+++ b/ForgeShortUrl/setup.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from setuptools import setup, find_packages
 
 
diff --git a/ForgeTracker/forgetracker/command/fix_discussion.py b/ForgeTracker/forgetracker/command/fix_discussion.py
index a85add1..4938222 100644
--- a/ForgeTracker/forgetracker/command/fix_discussion.py
+++ b/ForgeTracker/forgetracker/command/fix_discussion.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from bson import ObjectId
 from bson.errors import InvalidId
 from ming.orm import ThreadLocalORMSession
diff --git a/ForgeTracker/forgetracker/config/resources.py b/ForgeTracker/forgetracker/config/resources.py
index 95b4eaf..b26d4df 100644
--- a/ForgeTracker/forgetracker/config/resources.py
+++ b/ForgeTracker/forgetracker/config/resources.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import pkg_resources
 
 
diff --git a/ForgeTracker/forgetracker/import_support.py b/ForgeTracker/forgetracker/import_support.py
index fe789a5..6b3faaf 100644
--- a/ForgeTracker/forgetracker/import_support.py
+++ b/ForgeTracker/forgetracker/import_support.py
@@ -17,6 +17,7 @@
 
 #-*- python -*-
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import json
 from datetime import datetime
diff --git a/ForgeTracker/forgetracker/model/__init__.py b/ForgeTracker/forgetracker/model/__init__.py
index 2585be9..891d79e 100644
--- a/ForgeTracker/forgetracker/model/__init__.py
+++ b/ForgeTracker/forgetracker/model/__init__.py
@@ -15,4 +15,5 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
-from ticket import Globals, Bin, Ticket, TicketAttachment, MovedTicket
+from __future__ import absolute_import
+from .ticket import Globals, Bin, Ticket, TicketAttachment, MovedTicket
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index a98ee03..c9aaf8e 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import urllib
 import json
diff --git a/ForgeTracker/forgetracker/plugins.py b/ForgeTracker/forgetracker/plugins.py
index 676deb2..fd017f8 100644
--- a/ForgeTracker/forgetracker/plugins.py
+++ b/ForgeTracker/forgetracker/plugins.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import absolute_import
 import logging
 
 from tg import config
diff --git a/ForgeTracker/forgetracker/search.py b/ForgeTracker/forgetracker/search.py
index 088d9bf..c4dbe1c 100644
--- a/ForgeTracker/forgetracker/search.py
+++ b/ForgeTracker/forgetracker/search.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 
 from allura.lib.search import search
diff --git a/ForgeTracker/forgetracker/site_stats.py b/ForgeTracker/forgetracker/site_stats.py
index 69f552a..5be3662 100644
--- a/ForgeTracker/forgetracker/site_stats.py
+++ b/ForgeTracker/forgetracker/site_stats.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from datetime import datetime, timedelta
 
 from bson import ObjectId
diff --git a/ForgeTracker/forgetracker/tasks.py b/ForgeTracker/forgetracker/tasks.py
index d3217a0..363c0a4 100644
--- a/ForgeTracker/forgetracker/tasks.py
+++ b/ForgeTracker/forgetracker/tasks.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from datetime import datetime
 
diff --git a/ForgeTracker/forgetracker/tests/command/test_fix_discussion.py b/ForgeTracker/forgetracker/tests/command/test_fix_discussion.py
index 161852e..2831835 100644
--- a/ForgeTracker/forgetracker/tests/command/test_fix_discussion.py
+++ b/ForgeTracker/forgetracker/tests/command/test_fix_discussion.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from ming.orm import session
 from nose.tools import assert_equal, assert_not_equal
 import pkg_resources
diff --git a/ForgeTracker/forgetracker/tests/functional/test_rest.py b/ForgeTracker/forgetracker/tests/functional/test_rest.py
index 8dcd154..2ed8674 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_rest.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_rest.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 
 from datadiff.tools import assert_equal
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index 0428654..c9770d3 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from datetime import datetime
 import urllib
 import os
diff --git a/ForgeTracker/forgetracker/tests/test_app.py b/ForgeTracker/forgetracker/tests/test_app.py
index b349988..d902a8d 100644
--- a/ForgeTracker/forgetracker/tests/test_app.py
+++ b/ForgeTracker/forgetracker/tests/test_app.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import tempfile
 import json
 import operator
diff --git a/ForgeTracker/forgetracker/tests/test_tracker_roles.py b/ForgeTracker/forgetracker/tests/test_tracker_roles.py
index 2cc33cd..c3bec8b 100644
--- a/ForgeTracker/forgetracker/tests/test_tracker_roles.py
+++ b/ForgeTracker/forgetracker/tests/test_tracker_roles.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c, app_globals as g
 
 from alluratest.controller import setup_basic_test, setup_global_objects
diff --git a/ForgeTracker/forgetracker/tests/unit/__init__.py b/ForgeTracker/forgetracker/tests/unit/__init__.py
index 7065226..6e79bcc 100644
--- a/ForgeTracker/forgetracker/tests/unit/__init__.py
+++ b/ForgeTracker/forgetracker/tests/unit/__init__.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 import tg
 from ming.orm.ormsession import ThreadLocalORMSession
diff --git a/ForgeTracker/forgetracker/tests/unit/test_globals_model.py b/ForgeTracker/forgetracker/tests/unit/test_globals_model.py
index 93ecf32..b047539 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_globals_model.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_globals_model.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from datetime import datetime, timedelta
 
 import mock
diff --git a/ForgeTracker/forgetracker/tests/unit/test_milestone_controller.py b/ForgeTracker/forgetracker/tests/unit/test_milestone_controller.py
index 00d2382..7795434 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_milestone_controller.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_milestone_controller.py
@@ -19,6 +19,7 @@
 
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from mock import Mock
 from nose.tools import assert_equal
 
diff --git a/ForgeTracker/forgetracker/tests/unit/test_root_controller.py b/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
index fe8c304..5020a21 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import unittest
 
 from mock import Mock, patch
diff --git a/ForgeTracker/forgetracker/tests/unit/test_search.py b/ForgeTracker/forgetracker/tests/unit/test_search.py
index 421a780..2a9f308 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_search.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_search.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import mock
 from nose.tools import assert_equal
 from forgetracker.search import get_facets, query_filter_choices
diff --git a/ForgeTracker/forgetracker/tests/unit/test_ticket_custom_fields_form.py b/ForgeTracker/forgetracker/tests/unit/test_ticket_custom_fields_form.py
index b97a4c8..2138af6 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_ticket_custom_fields_form.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_ticket_custom_fields_form.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from ming.orm.ormsession import ThreadLocalORMSession
 from ming.base import Object
 
diff --git a/ForgeTracker/forgetracker/tests/unit/test_ticket_form.py b/ForgeTracker/forgetracker/tests/unit/test_ticket_form.py
index 982e801..2de06a9 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_ticket_form.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_ticket_form.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from ming.orm.ormsession import ThreadLocalORMSession
 
 from tg import tmpl_context as c
diff --git a/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py b/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py
index 55b5f18..d4492b5 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 from datetime import datetime
 import urllib2
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index ddd836b..b95c94e 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import re
 from datetime import datetime, timedelta
diff --git a/ForgeTracker/forgetracker/widgets/admin.py b/ForgeTracker/forgetracker/widgets/admin.py
index 25ab534..a36e11d 100644
--- a/ForgeTracker/forgetracker/widgets/admin.py
+++ b/ForgeTracker/forgetracker/widgets/admin.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import ew.jinja2_ew as ew
 
 from formencode import validators as fev
diff --git a/ForgeTracker/forgetracker/widgets/admin_custom_fields.py b/ForgeTracker/forgetracker/widgets/admin_custom_fields.py
index 04d1308..676a957 100644
--- a/ForgeTracker/forgetracker/widgets/admin_custom_fields.py
+++ b/ForgeTracker/forgetracker/widgets/admin_custom_fields.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import ew as ew_core
 import ew.jinja2_ew as ew
 
diff --git a/ForgeTracker/forgetracker/widgets/bin_form.py b/ForgeTracker/forgetracker/widgets/bin_form.py
index bda0d78..a18cff2 100644
--- a/ForgeTracker/forgetracker/widgets/bin_form.py
+++ b/ForgeTracker/forgetracker/widgets/bin_form.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import ew
 from ew import jinja2_ew
 from allura.lib import validators as V
diff --git a/ForgeTracker/forgetracker/widgets/ticket_form.py b/ForgeTracker/forgetracker/widgets/ticket_form.py
index 297bb33..b7674ec 100644
--- a/ForgeTracker/forgetracker/widgets/ticket_form.py
+++ b/ForgeTracker/forgetracker/widgets/ticket_form.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 from formencode import validators as fev
 from webhelpers.html.builder import literal
diff --git a/ForgeTracker/forgetracker/widgets/ticket_search.py b/ForgeTracker/forgetracker/widgets/ticket_search.py
index cd6ebf1..44bc9da 100644
--- a/ForgeTracker/forgetracker/widgets/ticket_search.py
+++ b/ForgeTracker/forgetracker/widgets/ticket_search.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import ew as ew_core
 import ew.jinja2_ew as ew
 
diff --git a/ForgeTracker/setup.py b/ForgeTracker/setup.py
index 7837afb..d6bf211 100644
--- a/ForgeTracker/setup.py
+++ b/ForgeTracker/setup.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from setuptools import setup, find_packages
 
 from forgetracker.version import __version__
diff --git a/ForgeUserStats/forgeuserstats/controllers/userstats.py b/ForgeUserStats/forgeuserstats/controllers/userstats.py
index c885386..f151145 100644
--- a/ForgeUserStats/forgeuserstats/controllers/userstats.py
+++ b/ForgeUserStats/forgeuserstats/controllers/userstats.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from datetime import datetime
 import re
 
diff --git a/ForgeUserStats/forgeuserstats/main.py b/ForgeUserStats/forgeuserstats/main.py
index 0629d8b..86d4441 100644
--- a/ForgeUserStats/forgeuserstats/main.py
+++ b/ForgeUserStats/forgeuserstats/main.py
@@ -17,6 +17,7 @@
 
 #-*- python -*-
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from tg import tmpl_context as c
 from datetime import datetime
@@ -25,8 +26,8 @@ from allura.app import Application, SitemapEntry
 from allura.lib import helpers as h
 from allura import model as M
 from allura.eventslistener import EventsListener
-from model.stats import UserStats
-from controllers.userstats import ForgeUserStatsController
+from .model.stats import UserStats
+from .controllers.userstats import ForgeUserStatsController
 
 from forgeuserstats import version
 
diff --git a/ForgeUserStats/forgeuserstats/model/stats.py b/ForgeUserStats/forgeuserstats/model/stats.py
index 1298a09..7c0f050 100644
--- a/ForgeUserStats/forgeuserstats/model/stats.py
+++ b/ForgeUserStats/forgeuserstats/model/stats.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from ming.orm import FieldProperty
 from ming import schema as S
 from datetime import datetime, timedelta
diff --git a/ForgeUserStats/forgeuserstats/tests/test_model.py b/ForgeUserStats/forgeuserstats/tests/test_model.py
index da5a5dd..afa94a1 100644
--- a/ForgeUserStats/forgeuserstats/tests/test_model.py
+++ b/ForgeUserStats/forgeuserstats/tests/test_model.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import pkg_resources
 import unittest
 from datetime import datetime, timedelta
diff --git a/ForgeUserStats/forgeuserstats/tests/test_stats.py b/ForgeUserStats/forgeuserstats/tests/test_stats.py
index c858d78..6ba171f 100644
--- a/ForgeUserStats/forgeuserstats/tests/test_stats.py
+++ b/ForgeUserStats/forgeuserstats/tests/test_stats.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import pkg_resources
 import unittest
 
diff --git a/ForgeUserStats/forgeuserstats/widgets/forms.py b/ForgeUserStats/forgeuserstats/widgets/forms.py
index 7b73715..dfdbd96 100644
--- a/ForgeUserStats/forgeuserstats/widgets/forms.py
+++ b/ForgeUserStats/forgeuserstats/widgets/forms.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from allura.lib.widgets.forms import ForgeForm
 
 import ew as ew_core
diff --git a/ForgeUserStats/setup.py b/ForgeUserStats/setup.py
index df68a2b..09a870a 100644
--- a/ForgeUserStats/setup.py
+++ b/ForgeUserStats/setup.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from setuptools import setup, find_packages
 
 from forgeuserstats.version import __version__
diff --git a/ForgeWiki/forgewiki/converters.py b/ForgeWiki/forgewiki/converters.py
index c4dd2f3..072a178 100644
--- a/ForgeWiki/forgewiki/converters.py
+++ b/ForgeWiki/forgewiki/converters.py
@@ -17,6 +17,7 @@
 
 #-*- python -*-
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import re
 from bs4 import BeautifulSoup
 import six
diff --git a/ForgeWiki/forgewiki/model/__init__.py b/ForgeWiki/forgewiki/model/__init__.py
index 02aa205..e638f51 100644
--- a/ForgeWiki/forgewiki/model/__init__.py
+++ b/ForgeWiki/forgewiki/model/__init__.py
@@ -15,4 +15,5 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
-from wiki import Page, WikiAttachment, Globals, PageHistory
+from __future__ import absolute_import
+from .wiki import Page, WikiAttachment, Globals, PageHistory
diff --git a/ForgeWiki/forgewiki/model/wiki.py b/ForgeWiki/forgewiki/model/wiki.py
index a829e10..ef081d1 100644
--- a/ForgeWiki/forgewiki/model/wiki.py
+++ b/ForgeWiki/forgewiki/model/wiki.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from datetime import datetime
 import difflib
 import os
diff --git a/ForgeWiki/forgewiki/tests/functional/test_rest.py b/ForgeWiki/forgewiki/tests/functional/test_rest.py
index 7d2e795..e29375d 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_rest.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_rest.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 
 from nose.tools import assert_equal, assert_in, assert_not_equal
diff --git a/ForgeWiki/forgewiki/tests/functional/test_root.py b/ForgeWiki/forgewiki/tests/functional/test_root.py
index 16b529f..49f30da 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_root.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_root.py
@@ -19,6 +19,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import os
 import StringIO
 import allura
diff --git a/ForgeWiki/forgewiki/tests/test_app.py b/ForgeWiki/forgewiki/tests/test_app.py
index 4bdba8e..6bfb224 100644
--- a/ForgeWiki/forgewiki/tests/test_app.py
+++ b/ForgeWiki/forgewiki/tests/test_app.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import datetime
 import tempfile
 import json
diff --git a/ForgeWiki/forgewiki/tests/test_converters.py b/ForgeWiki/forgewiki/tests/test_converters.py
index 5e2bdfa..398c0a8 100644
--- a/ForgeWiki/forgewiki/tests/test_converters.py
+++ b/ForgeWiki/forgewiki/tests/test_converters.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from IPython.testing.decorators import module_not_available, skipif
 
 from forgewiki import converters
diff --git a/ForgeWiki/forgewiki/tests/test_models.py b/ForgeWiki/forgewiki/tests/test_models.py
index e078743..199ec63 100644
--- a/ForgeWiki/forgewiki/tests/test_models.py
+++ b/ForgeWiki/forgewiki/tests/test_models.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c
 from ming.orm import session
 
diff --git a/ForgeWiki/forgewiki/tests/test_wiki_roles.py b/ForgeWiki/forgewiki/tests/test_wiki_roles.py
index 21918a0..856dd2b 100644
--- a/ForgeWiki/forgewiki/tests/test_wiki_roles.py
+++ b/ForgeWiki/forgewiki/tests/test_wiki_roles.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from tg import tmpl_context as c, app_globals as g
 
 from nose.tools import assert_equal
diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index 5b550af..292f055 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -17,6 +17,7 @@
 
 #-*- python -*-
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import json
 import logging
 import os
diff --git a/ForgeWiki/setup.py b/ForgeWiki/setup.py
index 52c332f..626465a 100644
--- a/ForgeWiki/setup.py
+++ b/ForgeWiki/setup.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from setuptools import setup, find_packages
 
 from forgewiki.version import __version__
diff --git a/fuse/accessfs.py b/fuse/accessfs.py
index f004b0e..9f9805b 100644
--- a/fuse/accessfs.py
+++ b/fuse/accessfs.py
@@ -19,6 +19,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import os
 import json
 import urllib
diff --git a/scripts/ApacheAccessHandler.py b/scripts/ApacheAccessHandler.py
index c9e8900..3b1b1bd 100644
--- a/scripts/ApacheAccessHandler.py
+++ b/scripts/ApacheAccessHandler.py
@@ -30,6 +30,7 @@ this authorization code without Allura set up and configured on the git host.
 
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from mod_python import apache
 import os
 import json
diff --git a/scripts/add_user_to_group.py b/scripts/add_user_to_group.py
index 96835b5..7ca1012 100644
--- a/scripts/add_user_to_group.py
+++ b/scripts/add_user_to_group.py
@@ -37,6 +37,7 @@ Example:
 """
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from allura import model as M
 from ming.orm import ThreadLocalORMSession
 
diff --git a/scripts/changelog.py b/scripts/changelog.py
index bf803b8..cb1fa2f 100755
--- a/scripts/changelog.py
+++ b/scripts/changelog.py
@@ -19,6 +19,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import sys
 import re
 import git
diff --git a/scripts/create-allura-sitemap.py b/scripts/create-allura-sitemap.py
index 7e5b31b..30164db 100644
--- a/scripts/create-allura-sitemap.py
+++ b/scripts/create-allura-sitemap.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from allura.scripts.create_sitemap_files import CreateSitemapFiles
 
 # this file exists for backwards compatibility
diff --git a/scripts/migrations/013-update-ordinals.py b/scripts/migrations/013-update-ordinals.py
index a6dcea0..94b1a43 100644
--- a/scripts/migrations/013-update-ordinals.py
+++ b/scripts/migrations/013-update-ordinals.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import sys
 import logging
 
diff --git a/scripts/migrations/015-add-neighborhood_id-to-blog-posts.py b/scripts/migrations/015-add-neighborhood_id-to-blog-posts.py
index 02bfb91..e1edca2 100644
--- a/scripts/migrations/015-add-neighborhood_id-to-blog-posts.py
+++ b/scripts/migrations/015-add-neighborhood_id-to-blog-posts.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 from tg import tmpl_context as c
diff --git a/scripts/migrations/018-add-svn-checkout-url.py b/scripts/migrations/018-add-svn-checkout-url.py
index 372c6fb..e865cc6 100644
--- a/scripts/migrations/018-add-svn-checkout-url.py
+++ b/scripts/migrations/018-add-svn-checkout-url.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from allura import model as M
 from ming.orm import ThreadLocalORMSession
 
diff --git a/scripts/migrations/020-remove-wiki-title-slashes.py b/scripts/migrations/020-remove-wiki-title-slashes.py
index c7bbea8..54b5049 100644
--- a/scripts/migrations/020-remove-wiki-title-slashes.py
+++ b/scripts/migrations/020-remove-wiki-title-slashes.py
@@ -17,6 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import logging
 
 from tg import tmpl_context as c
diff --git a/scripts/migrations/022-change-anon-display-name.py b/scripts/migrations/022-change-anon-display-name.py
index 8722d8e..fe378d4 100644
--- a/scripts/migrations/022-change-anon-display-name.py
+++ b/scripts/migrations/022-change-anon-display-name.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from ming.orm.ormsession import ThreadLocalORMSession
 from allura import model as M
 
diff --git a/scripts/migrations/024-migrate-custom-profile-text.py b/scripts/migrations/024-migrate-custom-profile-text.py
index bf851b5..51ccd43 100644
--- a/scripts/migrations/024-migrate-custom-profile-text.py
+++ b/scripts/migrations/024-migrate-custom-profile-text.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import re
 
diff --git a/scripts/migrations/025-add-is-nbhd-project.py b/scripts/migrations/025-add-is-nbhd-project.py
index e2e7fdf..fcf7cb0 100644
--- a/scripts/migrations/025-add-is-nbhd-project.py
+++ b/scripts/migrations/025-add-is-nbhd-project.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 from allura import model as M
diff --git a/scripts/migrations/026-install-activity-tool.py b/scripts/migrations/026-install-activity-tool.py
index 620a614..ac876aa 100644
--- a/scripts/migrations/026-install-activity-tool.py
+++ b/scripts/migrations/026-install-activity-tool.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 from ming.orm import ThreadLocalORMSession
diff --git a/scripts/migrations/027-change-ticket-write-permissions.py b/scripts/migrations/027-change-ticket-write-permissions.py
index 4f51e20..5e909b1 100644
--- a/scripts/migrations/027-change-ticket-write-permissions.py
+++ b/scripts/migrations/027-change-ticket-write-permissions.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from ming.orm import ThreadLocalORMSession
 
diff --git a/scripts/migrations/028-remove-svn-trees.py b/scripts/migrations/028-remove-svn-trees.py
index f0ba538..dbf3ee2 100644
--- a/scripts/migrations/028-remove-svn-trees.py
+++ b/scripts/migrations/028-remove-svn-trees.py
@@ -17,6 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import logging
 
 from ming.orm import ThreadLocalORMSession
diff --git a/scripts/migrations/029-set-mailbox-queue_empty.py b/scripts/migrations/029-set-mailbox-queue_empty.py
index 0f936fe..00a2835 100644
--- a/scripts/migrations/029-set-mailbox-queue_empty.py
+++ b/scripts/migrations/029-set-mailbox-queue_empty.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 from allura import model as M
diff --git a/scripts/migrations/031-set-user-pending-to-false.py b/scripts/migrations/031-set-user-pending-to-false.py
index ef0c67e..d39b357 100644
--- a/scripts/migrations/031-set-user-pending-to-false.py
+++ b/scripts/migrations/031-set-user-pending-to-false.py
@@ -17,6 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import logging
 
 from ming.odm import ThreadLocalORMSession, state
diff --git a/scripts/migrations/032-subscribe-merge-request-submitters.py b/scripts/migrations/032-subscribe-merge-request-submitters.py
index 791cf3c..66a7132 100644
--- a/scripts/migrations/032-subscribe-merge-request-submitters.py
+++ b/scripts/migrations/032-subscribe-merge-request-submitters.py
@@ -17,6 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import logging
 
 from ming.odm import ThreadLocalORMSession, state
diff --git a/scripts/migrations/033-change-comment-anon-permissions.py b/scripts/migrations/033-change-comment-anon-permissions.py
index a418a1b..62bb3e2 100644
--- a/scripts/migrations/033-change-comment-anon-permissions.py
+++ b/scripts/migrations/033-change-comment-anon-permissions.py
@@ -17,6 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import sys
 import logging
 from ming.orm import ThreadLocalORMSession, session
diff --git a/scripts/migrations/034-update_subscriptions_ticket_and_mr_titles.py b/scripts/migrations/034-update_subscriptions_ticket_and_mr_titles.py
index 44093de..16f5cf0 100644
--- a/scripts/migrations/034-update_subscriptions_ticket_and_mr_titles.py
+++ b/scripts/migrations/034-update_subscriptions_ticket_and_mr_titles.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import re
 import sys
diff --git a/scripts/new_ticket.py b/scripts/new_ticket.py
index 8574220..47dd921 100755
--- a/scripts/new_ticket.py
+++ b/scripts/new_ticket.py
@@ -18,6 +18,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import sys
 import argparse
 import requests
diff --git a/scripts/perf/benchmark-scm.py b/scripts/perf/benchmark-scm.py
index 9bb8697..717da23 100755
--- a/scripts/perf/benchmark-scm.py
+++ b/scripts/perf/benchmark-scm.py
@@ -20,6 +20,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import os
 import sys
 import argparse
diff --git a/scripts/perf/call_count.py b/scripts/perf/call_count.py
index 658e3db..2b3e1ce 100755
--- a/scripts/perf/call_count.py
+++ b/scripts/perf/call_count.py
@@ -19,6 +19,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import argparse
 import json
 import logging
diff --git a/scripts/perf/generate-projects.py b/scripts/perf/generate-projects.py
index 0b60da3..1591170 100644
--- a/scripts/perf/generate-projects.py
+++ b/scripts/perf/generate-projects.py
@@ -17,6 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import re
 from ming.odm import ThreadLocalORMSession
 from allura import model as M
diff --git a/scripts/perf/load-up-forum.py b/scripts/perf/load-up-forum.py
index 38d134d..cce16d9 100644
--- a/scripts/perf/load-up-forum.py
+++ b/scripts/perf/load-up-forum.py
@@ -17,6 +17,7 @@
 
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import uuid
 from ming.orm import ThreadLocalORMSession, session
diff --git a/scripts/perf/md_perf.py b/scripts/perf/md_perf.py
index 63e8fac..e12f088 100644
--- a/scripts/perf/md_perf.py
+++ b/scripts/perf/md_perf.py
@@ -47,6 +47,7 @@ sys     0m1.112s
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import argparse
 import cProfile
 import time
diff --git a/scripts/perf/parse_timings.py b/scripts/perf/parse_timings.py
index 706482f..e85243c 100644
--- a/scripts/perf/parse_timings.py
+++ b/scripts/perf/parse_timings.py
@@ -19,6 +19,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import json
 from datetime import datetime
 import argparse
diff --git a/scripts/perf/sstress.py b/scripts/perf/sstress.py
index 332edfd..04c0a22 100644
--- a/scripts/perf/sstress.py
+++ b/scripts/perf/sstress.py
@@ -23,6 +23,7 @@ sstress - an SMTP stress testing tool
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import smtplib
 import threading
 import time
diff --git a/scripts/perf/test_git_lcd.py b/scripts/perf/test_git_lcd.py
index 1557aca..6993f39 100644
--- a/scripts/perf/test_git_lcd.py
+++ b/scripts/perf/test_git_lcd.py
@@ -19,6 +19,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import sys
 import os
 from glob import glob
diff --git a/scripts/project-import.py b/scripts/project-import.py
index c210989..3edb71b 100644
--- a/scripts/project-import.py
+++ b/scripts/project-import.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import bson
 import datetime
 import json
diff --git a/scripts/publicize-neighborhood.py b/scripts/publicize-neighborhood.py
index 804d0e4..fcc4d1f 100644
--- a/scripts/publicize-neighborhood.py
+++ b/scripts/publicize-neighborhood.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import sys
 
diff --git a/scripts/rethumb.py b/scripts/rethumb.py
index 8d84e5d..7a3d61a 100644
--- a/scripts/rethumb.py
+++ b/scripts/rethumb.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import sys
 
 import PIL
diff --git a/scripts/scrub-allura-data.py b/scripts/scrub-allura-data.py
index 8902426..9aeb054 100644
--- a/scripts/scrub-allura-data.py
+++ b/scripts/scrub-allura-data.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 import sys
 
diff --git a/scripts/teamforge-import.py b/scripts/teamforge-import.py
index b6d04c5..4e875bf 100644
--- a/scripts/teamforge-import.py
+++ b/scripts/teamforge-import.py
@@ -17,6 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import logging
 from getpass import getpass
 from optparse import OptionParser
diff --git a/scripts/trac_export.py b/scripts/trac_export.py
index 6fe9655..ae0e112 100755
--- a/scripts/trac_export.py
+++ b/scripts/trac_export.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 if __name__ == '__main__':
     from allura.scripts.trac_export import main
     main()
diff --git a/scripts/trac_export_wiki.py b/scripts/trac_export_wiki.py
index ef62ddf..321e4ed 100755
--- a/scripts/trac_export_wiki.py
+++ b/scripts/trac_export_wiki.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 import sys
 from optparse import OptionParser
 
diff --git a/scripts/trac_import.py b/scripts/trac_import.py
index ad070a7..fda168b 100644
--- a/scripts/trac_import.py
+++ b/scripts/trac_import.py
@@ -17,6 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import json
 from optparse import OptionParser
 
diff --git a/scripts/wiki-copy.py b/scripts/wiki-copy.py
index f557445..6f427b6 100644
--- a/scripts/wiki-copy.py
+++ b/scripts/wiki-copy.py
@@ -19,6 +19,7 @@
 
 from __future__ import unicode_literals
 from __future__ import print_function
+from __future__ import absolute_import
 import os
 import sys
 import urllib


[allura] 25/41: [#8349] python-modernize -n -w --no-diffs -f idioms .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 158a4722e6542a52f07e44ca47406a448525032f
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 14:46:15 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f idioms .
---
 Allura/allura/controllers/repository.py                 |  2 +-
 Allura/allura/lib/AsciiDammit.py                        |  2 +-
 Allura/allura/lib/helpers.py                            |  2 +-
 Allura/allura/lib/mail_util.py                          |  4 ++--
 Allura/allura/lib/widgets/project_list.py               | 10 +++++-----
 Allura/allura/scripts/trac_export.py                    |  2 +-
 Allura/allura/tests/model/test_artifact.py              |  2 +-
 Allura/allura/tests/model/test_filesystem.py            |  4 ++--
 Allura/allura/tests/test_helpers.py                     |  2 +-
 ForgeBlog/forgeblog/main.py                             |  2 +-
 ForgeTracker/forgetracker/model/ticket.py               |  2 +-
 ForgeTracker/forgetracker/tests/functional/test_root.py |  2 +-
 ForgeWiki/forgewiki/wiki_main.py                        |  3 +--
 scripts/trac_import.py                                  |  2 +-
 14 files changed, 20 insertions(+), 21 deletions(-)

diff --git a/Allura/allura/controllers/repository.py b/Allura/allura/controllers/repository.py
index 1465b12..da8b834 100644
--- a/Allura/allura/controllers/repository.py
+++ b/Allura/allura/controllers/repository.py
@@ -699,7 +699,7 @@ class CommitBrowser(BaseController):
         # ('removed', u'bbb.txt', 'tree', None),
         # ('removed', u'ddd.txt', 'tree', None),
         # ('changed', u'ccc.txt', 'blob', True)]
-        result['artifacts'].sort(key=lambda x: x[1]['old'] if(type(x[1]) == dict) else x[1])
+        result['artifacts'].sort(key=lambda x: x[1]['old'] if(isinstance(x[1], dict)) else x[1])
         return result
 
     @expose('jinja:allura:templates/repo/commit_basic.html')
diff --git a/Allura/allura/lib/AsciiDammit.py b/Allura/allura/lib/AsciiDammit.py
index df0effa..db0604c 100644
--- a/Allura/allura/lib/AsciiDammit.py
+++ b/Allura/allura/lib/AsciiDammit.py
@@ -176,7 +176,7 @@ def _repl(match, html=0):
     "Replace the matched character with its HTML or ASCII equivalent."
     g = match.group(0)
     a = CHARS.get(g, g)
-    if type(a) == types.TupleType:
+    if isinstance(a, types.TupleType):
         a = a[html]
         if html:
             a = '&' + a + ';'
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index 1efbc39..8f075eb 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -322,7 +322,7 @@ def set_context(project_shortname_or_id, mount_point=None, app_config_id=None, n
         p = model.Project.query.get(_id=ObjectId(str(project_shortname_or_id)))
     except InvalidId:
         p = None
-    if p is None and type(project_shortname_or_id) != ObjectId:
+    if p is None and not isinstance(project_shortname_or_id, ObjectId):
         if neighborhood is None:
             raise TypeError('neighborhood is required; it must not be None')
         if not isinstance(neighborhood, model.Neighborhood):
diff --git a/Allura/allura/lib/mail_util.py b/Allura/allura/lib/mail_util.py
index b00019e..cce61a9 100644
--- a/Allura/allura/lib/mail_util.py
+++ b/Allura/allura/lib/mail_util.py
@@ -55,11 +55,11 @@ def Header(text, *more_text):
     # email.header.Header handles str vs unicode differently
     # see
     # http://docs.python.org/library/email.header.html#email.header.Header.append
-    if type(text) != six.text_type:
+    if not isinstance(text, six.text_type):
         raise TypeError('This must be unicode: %r' % text)
     head = header.Header(text)
     for m in more_text:
-        if type(m) != six.text_type:
+        if not isinstance(m, six.text_type):
             raise TypeError('This must be unicode: %r' % text)
         head.append(m)
     return head
diff --git a/Allura/allura/lib/widgets/project_list.py b/Allura/allura/lib/widgets/project_list.py
index 71a6b78..1c53cf0 100644
--- a/Allura/allura/lib/widgets/project_list.py
+++ b/Allura/allura/lib/widgets/project_list.py
@@ -52,21 +52,21 @@ class ProjectSummary(ew_core.Widget):
         if response['accolades'] is None:
             response['accolades'] = value.accolades
 
-        if type(response['columns']) == six.text_type:
+        if isinstance(response['columns'], six.text_type):
             response['columns'] = int(response['columns'])
 
         true_list = ['true', 't', '1', 'yes', 'y']
-        if type(response['show_proj_icon']) == six.text_type:
+        if isinstance(response['show_proj_icon'], six.text_type):
             if response['show_proj_icon'].lower() in true_list:
                 response['show_proj_icon'] = True
             else:
                 response['show_proj_icon'] = False
-        if type(response['show_download_button']) == six.text_type:
+        if isinstance(response['show_download_button'], six.text_type):
             if response['show_download_button'].lower() in true_list:
                 response['show_download_button'] = True
             else:
                 response['show_download_button'] = False
-        if type(response['show_awards_banner']) == six.text_type:
+        if isinstance(response['show_awards_banner'], six.text_type):
             if response['show_awards_banner'].lower() in true_list:
                 response['show_awards_banner'] = True
             else:
@@ -104,7 +104,7 @@ class ProjectList(ew_core.Widget):
         if response['accolades_index'] is None and response['show_awards_banner']:
             response['accolades_index'] = M.Project.accolades_index(projects)
 
-        if type(response['columns']) == six.text_type:
+        if isinstance(response['columns'], six.text_type):
             response['columns'] = int(response['columns'])
 
         return response
diff --git a/Allura/allura/scripts/trac_export.py b/Allura/allura/scripts/trac_export.py
index c9b411b..9d6a991 100644
--- a/Allura/allura/scripts/trac_export.py
+++ b/Allura/allura/scripts/trac_export.py
@@ -212,7 +212,7 @@ class TracExport(object):
                 text=re.compile('added by')).nextSibling.renderContents()
             d['description'] = ''
             # Skip whitespace
-            while attach.nextSibling and type(attach.nextSibling) is NavigableString:
+            while attach.nextSibling and isinstance(attach.nextSibling, NavigableString):
                 attach = attach.nextSibling
             # if there's a description, there will be a <dd> element, other
             # immediately next <dt>
diff --git a/Allura/allura/tests/model/test_artifact.py b/Allura/allura/tests/model/test_artifact.py
index e0d15d9..cec7804 100644
--- a/Allura/allura/tests/model/test_artifact.py
+++ b/Allura/allura/tests/model/test_artifact.py
@@ -197,7 +197,7 @@ def test_messages_unknown_lookup():
     from bson import ObjectId
     m = Checkmessage()
     m.author_id = ObjectId()  # something new
-    assert type(m.author()) == M.User, type(m.author())
+    assert isinstance(m.author(), M.User), type(m.author())
     assert m.author() == M.User.anonymous()
 
 
diff --git a/Allura/allura/tests/model/test_filesystem.py b/Allura/allura/tests/model/test_filesystem.py
index 104267a..d757a4f 100644
--- a/Allura/allura/tests/model/test_filesystem.py
+++ b/Allura/allura/tests/model/test_filesystem.py
@@ -199,7 +199,7 @@ class TestFile(TestCase):
         c.app.config._id = None
         attachment = M.BaseAttachment.save_attachment('user.png', fp,
                                                       save_original=True)
-        assert type(attachment) != tuple   # tuple is for (img, thumb) pairs
+        assert not isinstance(attachment, tuple)   # tuple is for (img, thumb) pairs
         assert_equal(attachment.length, 500)
         assert_equal(attachment.filename, 'user.png')
 
@@ -211,7 +211,7 @@ class TestFile(TestCase):
         attachment = M.BaseAttachment.save_attachment(
             b'Strukturpr\xfcfung.dvi', fp,
             save_original=True)
-        assert type(attachment) != tuple   # tuple is for (img, thumb) pairs
+        assert not isinstance(attachment, tuple)   # tuple is for (img, thumb) pairs
         assert_equal(attachment.filename, 'Strukturpr\xfcfung.dvi')
 
     def _assert_content(self, f, content):
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index ecb265c..d5ea156 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -187,7 +187,7 @@ def test_context_setters():
 
 def test_encode_keys():
     kw = h.encode_keys({'foo': 5})
-    assert type(list(kw.keys())[0]) != six.text_type
+    assert not isinstance(list(kw.keys())[0], six.text_type)
 
 
 def test_ago():
diff --git a/ForgeBlog/forgeblog/main.py b/ForgeBlog/forgeblog/main.py
index 89d7ebd..98544b3 100644
--- a/ForgeBlog/forgeblog/main.py
+++ b/ForgeBlog/forgeblog/main.py
@@ -545,7 +545,7 @@ class BlogAdminController(DefaultAdminController):
     @require_post()
     def set_exfeed(self, new_exfeed=None, **kw):
         exfeed_val = kw.get('exfeed', [])
-        if type(exfeed_val) == six.text_type:
+        if isinstance(exfeed_val, six.text_type):
             tmp_exfeed_list = []
             tmp_exfeed_list.append(exfeed_val)
         else:
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index 99061c3..62f85c9 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -1176,7 +1176,7 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
     def __json__(self, posts_limit=None, is_export=False):
         parents_json = {}
         for parent in reversed(type(self).mro()):
-            if parent != type(self) and hasattr(parent, '__json__'):
+            if not isinstance(self, parent) and hasattr(parent, '__json__'):
                 kwargs = {}
                 if parent == VersionedArtifact:
                     kwargs['posts_limit'] = posts_limit
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index 294b01e..32b3942 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -87,7 +87,7 @@ class TrackerTestController(TestController):
                                 extra_environ=extra_environ)
         form = self._find_new_ticket_form(response)
         for k, v in six.iteritems(kw):
-            if type(v) == bool:
+            if isinstance(v, bool):
                 form['ticket_form.%s' % k] = v
             else:
                 form['ticket_form.%s' % k].force_value(v)
diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index 0c4f0de..75f289a 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -488,8 +488,7 @@ class RootController(BaseController, DispatchIndex, FeedController):
                         page_tags[label] = []
                     page_tags[label].append(page)
         count = len(page_tags)
-        name_labels = list(page_tags)
-        name_labels.sort()
+        name_labels = sorted(page_tags)
         return dict(labels=page_tags,
                     limit=limit,
                     count=count,
diff --git a/scripts/trac_import.py b/scripts/trac_import.py
index e9eed3c..5f14de7 100644
--- a/scripts/trac_import.py
+++ b/scripts/trac_import.py
@@ -42,7 +42,7 @@ def main():
         f = open(options.user_map_file)
         try:
             user_map = json.load(f)
-            if type(user_map) is not type({}):
+            if not isinstance(user_map, type({})):
                 raise ValueError
             for k, v in six.iteritems(user_map):
                 print(k, v)


[allura] 17/41: [#8349] python-modernize -n -w --no-diffs -f numliterals .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 215ee5f6b8ca2a66bbd8643b33f80d1145679971
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 14:12:11 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f numliterals .
---
 Allura/allura/lib/multifactor.py    | 2 +-
 Allura/ldap-setup.py                | 4 ++--
 Allura/ldap-userconfig.py           | 6 +++---
 ForgeGit/forgegit/model/git_repo.py | 2 +-
 ForgeSVN/forgesvn/model/svn.py      | 4 ++--
 5 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/Allura/allura/lib/multifactor.py b/Allura/allura/lib/multifactor.py
index 29ea612..c120a16 100644
--- a/Allura/allura/lib/multifactor.py
+++ b/Allura/allura/lib/multifactor.py
@@ -258,7 +258,7 @@ class GoogleAuthenticatorPamFilesystemMixin(object):
         if autocreate:
             userdir = os.path.dirname(self.config_file(user))
             if not os.path.exists(userdir):
-                os.makedirs(userdir, 0700)
+                os.makedirs(userdir, 0o700)
 
         try:
             with open(self.config_file(user)) as f:
diff --git a/Allura/ldap-setup.py b/Allura/ldap-setup.py
index 07dbe29..600c547 100644
--- a/Allura/ldap-setup.py
+++ b/Allura/ldap-setup.py
@@ -56,7 +56,7 @@ def main():
             run('ldapadd -Y EXTERNAL -H ldapi:/// -f %s' % name)
     with open('/etc/ldap.secret', 'w') as fp:
         fp.write(secret)
-    os.chmod('/etc/ldap.secret', 0400)
+    os.chmod('/etc/ldap.secret', 0o400)
     if get_value('add frontend ldif', 'y') == 'y':
         with tempfile(frontend_ldif, locals()) as name:
             run('ldapadd -c -x -D cn=admin,%s -W -f %s -y /etc/ldap.secret' %
@@ -77,7 +77,7 @@ def main():
         log.info('writing passwd')
         with open('/etc/ldapscripts/ldapscripts.passwd', 'w') as fp:
             fp.write(secret)
-        os.chmod('/etc/ldapscripts/ldapscripts.passwd', 0400)
+        os.chmod('/etc/ldapscripts/ldapscripts.passwd', 0o400)
         log.info('writing runtime')
         with open('/usr/share/ldapscripts/runtime.debian', 'w') as fp:
             fp.write(ldapscripts_debian)
diff --git a/Allura/ldap-userconfig.py b/Allura/ldap-userconfig.py
index c0f2330..4e29a60 100644
--- a/Allura/ldap-userconfig.py
+++ b/Allura/ldap-userconfig.py
@@ -39,8 +39,8 @@ def init(uname):
     os.mkdir(ssh)
     u = pwd.getpwnam(uname)
     g = grp.getgrnam('scm')
-    os.chmod(home, 0700)
-    os.chmod(ssh, 0700)
+    os.chmod(home, 0o700)
+    os.chmod(ssh, 0o700)
     os.chown(home, u.pw_uid, g.gr_gid)
     os.chown(ssh, u.pw_uid, g.gr_gid)
 
@@ -52,7 +52,7 @@ def upload(uname, pubkey):
     with open(keyfile, 'w') as fp:
         fp.write(pubkey)
     os.chown(keyfile, u.pw_uid, g.gr_gid)
-    os.chmod(keyfile, 0600)
+    os.chmod(keyfile, 0o600)
 
 if __name__ == '__main__':
     main()
diff --git a/ForgeGit/forgegit/model/git_repo.py b/ForgeGit/forgegit/model/git_repo.py
index 2c01380..513b0cc 100644
--- a/ForgeGit/forgegit/model/git_repo.py
+++ b/ForgeGit/forgegit/model/git_repo.py
@@ -487,7 +487,7 @@ class GitImplementation(M.RepositoryImplementation):
                           'hooks', 'post-receive')
         with open(fn, 'w') as fp:
             fp.write(text)
-        os.chmod(fn, 0755)
+        os.chmod(fn, 0o755)
 
     def _object(self, oid):
         evens = oid[::2]
diff --git a/ForgeSVN/forgesvn/model/svn.py b/ForgeSVN/forgesvn/model/svn.py
index 7bf084b..c91c1f9 100644
--- a/ForgeSVN/forgesvn/model/svn.py
+++ b/ForgeSVN/forgesvn/model/svn.py
@@ -236,7 +236,7 @@ class SVNImplementation(M.RepositoryImplementation):
                               'hooks', hook_name)
             with open(fn, 'wb') as fp:
                 fp.write('#!/bin/sh\n')
-            os.chmod(fn, 0755)
+            os.chmod(fn, 0o755)
 
         def clear_hook(hook_name):
             fn = os.path.join(self._repo.fs_path, self._repo.name,
@@ -611,7 +611,7 @@ class SVNImplementation(M.RepositoryImplementation):
                           'hooks', 'post-commit')
         with open(fn, 'wb') as fp:
             fp.write(text)
-        os.chmod(fn, 0755)
+        os.chmod(fn, 0o755)
 
     def _revno(self, oid):
         return int(oid.split(':')[1])


[allura] 14/41: [#8349] python-modernize -n -w --no-diffs -f libmodernize.fixes.fix_open .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit fb73880f0026e5ae96aa7eba46a883dfcd3f4b28
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 13:40:47 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f libmodernize.fixes.fix_open .
---
 Allura/allura/app.py                                           | 1 +
 Allura/allura/command/script.py                                | 1 +
 Allura/allura/lib/multifactor.py                               | 1 +
 Allura/allura/lib/spam/stopforumspamfilter.py                  | 1 +
 Allura/allura/model/filesystem.py                              | 1 +
 Allura/allura/model/repository.py                              | 1 +
 Allura/allura/scripts/create_sitemap_files.py                  | 1 +
 Allura/allura/scripts/trac_export.py                           | 1 +
 Allura/allura/tasks/export_tasks.py                            | 1 +
 Allura/allura/tests/functional/test_discuss.py                 | 1 +
 Allura/allura/tests/model/test_filesystem.py                   | 1 +
 Allura/allura/tests/test_globals.py                            | 1 +
 Allura/allura/tests/test_helpers.py                            | 1 +
 Allura/ldap-setup.py                                           | 1 +
 Allura/ldap-userconfig.py                                      | 1 +
 ForgeDiscussion/forgediscussion/tests/functional/test_forum.py | 1 +
 ForgeGit/forgegit/model/git_repo.py                            | 1 +
 ForgeGit/forgegit/tests/functional/test_controllers.py         | 1 +
 ForgeGit/forgegit/tests/model/test_repository.py               | 1 +
 ForgeImporters/forgeimporters/base.py                          | 1 +
 ForgeImporters/forgeimporters/forge/tracker.py                 | 1 +
 ForgeImporters/forgeimporters/trac/tests/test_tickets.py       | 1 +
 ForgeSVN/forgesvn/model/svn.py                                 | 1 +
 ForgeSVN/forgesvn/tests/model/test_repository.py               | 1 +
 ForgeWiki/forgewiki/tests/test_app.py                          | 1 +
 fuse/accessfs.py                                               | 1 +
 scripts/perf/call_count.py                                     | 1 +
 scripts/project-import.py                                      | 1 +
 scripts/teamforge-import.py                                    | 1 +
 scripts/trac_export_wiki.py                                    | 1 +
 scripts/trac_import.py                                         | 1 +
 scripts/wiki-copy.py                                           | 1 +
 32 files changed, 32 insertions(+)

diff --git a/Allura/allura/app.py b/Allura/allura/app.py
index 62ebca6..ad7db0c 100644
--- a/Allura/allura/app.py
+++ b/Allura/allura/app.py
@@ -50,6 +50,7 @@ from allura.lib.utils import permanent_redirect, ConfigProxy
 from allura import model as M
 from allura.tasks import index_tasks
 import six
+from io import open
 
 log = logging.getLogger(__name__)
 
diff --git a/Allura/allura/command/script.py b/Allura/allura/command/script.py
index f9767e2..42f0136 100644
--- a/Allura/allura/command/script.py
+++ b/Allura/allura/command/script.py
@@ -31,6 +31,7 @@ from ming.orm import session
 from allura.lib import helpers as h
 from allura.lib import utils
 from . import base
+from io import open
 
 
 class ScriptCommand(base.Command):
diff --git a/Allura/allura/lib/multifactor.py b/Allura/allura/lib/multifactor.py
index b756930..29ea612 100644
--- a/Allura/allura/lib/multifactor.py
+++ b/Allura/allura/lib/multifactor.py
@@ -42,6 +42,7 @@ from ming.odm import session
 from allura.model.multifactor import RecoveryCode
 from allura.lib.utils import umask
 import six
+from io import open
 
 
 log = logging.getLogger(__name__)
diff --git a/Allura/allura/lib/spam/stopforumspamfilter.py b/Allura/allura/lib/spam/stopforumspamfilter.py
index 24d040f..8915ecb 100644
--- a/Allura/allura/lib/spam/stopforumspamfilter.py
+++ b/Allura/allura/lib/spam/stopforumspamfilter.py
@@ -27,6 +27,7 @@ from tg import request
 from allura.lib import utils
 from allura.lib.spam import SpamFilter
 import six
+from io import open
 
 log = logging.getLogger(__name__)
 
diff --git a/Allura/allura/model/filesystem.py b/Allura/allura/model/filesystem.py
index 4bc9bf2..7bd726c 100644
--- a/Allura/allura/model/filesystem.py
+++ b/Allura/allura/model/filesystem.py
@@ -31,6 +31,7 @@ from ming.orm.declarative import MappedClass
 
 from .session import project_orm_session
 from allura.lib import utils
+from io import open
 
 log = logging.getLogger(__name__)
 
diff --git a/Allura/allura/model/repository.py b/Allura/allura/model/repository.py
index 790690d..160be35 100644
--- a/Allura/allura/model/repository.py
+++ b/Allura/allura/model/repository.py
@@ -60,6 +60,7 @@ from .monq_model import MonQTask
 from .project import AppConfig
 from .session import main_doc_session
 from .session import repository_orm_session
+from io import open
 
 
 log = logging.getLogger(__name__)
diff --git a/Allura/allura/scripts/create_sitemap_files.py b/Allura/allura/scripts/create_sitemap_files.py
index 8ed580e..e2347bb 100644
--- a/Allura/allura/scripts/create_sitemap_files.py
+++ b/Allura/allura/scripts/create_sitemap_files.py
@@ -45,6 +45,7 @@ from tg import config
 from allura import model as M
 from allura.lib import security, utils
 from allura.scripts import ScriptTask
+from io import open
 
 
 MAX_SITEMAP_URLS = 50000
diff --git a/Allura/allura/scripts/trac_export.py b/Allura/allura/scripts/trac_export.py
index 4cb4347..c9b411b 100644
--- a/Allura/allura/scripts/trac_export.py
+++ b/Allura/allura/scripts/trac_export.py
@@ -35,6 +35,7 @@ from bs4 import BeautifulSoup, NavigableString
 import dateutil.parser
 import pytz
 import six
+from io import open
 
 try:
     from forgeimporters.base import ProjectExtractor
diff --git a/Allura/allura/tasks/export_tasks.py b/Allura/allura/tasks/export_tasks.py
index 9614e28..dfc4d61 100644
--- a/Allura/allura/tasks/export_tasks.py
+++ b/Allura/allura/tasks/export_tasks.py
@@ -29,6 +29,7 @@ from allura.tasks import mail_tasks
 from allura.lib.decorators import task
 from allura.lib import helpers as h
 from allura.model.repository import zipdir
+from io import open
 
 
 log = logging.getLogger(__name__)
diff --git a/Allura/allura/tests/functional/test_discuss.py b/Allura/allura/tests/functional/test_discuss.py
index 51f84a1..97d0a90 100644
--- a/Allura/allura/tests/functional/test_discuss.py
+++ b/Allura/allura/tests/functional/test_discuss.py
@@ -27,6 +27,7 @@ from allura.tests import TestController
 from allura import model as M
 from allura.lib import helpers as h
 from tg import config
+from io import open
 
 
 
diff --git a/Allura/allura/tests/model/test_filesystem.py b/Allura/allura/tests/model/test_filesystem.py
index 545945f..8d4eff9 100644
--- a/Allura/allura/tests/model/test_filesystem.py
+++ b/Allura/allura/tests/model/test_filesystem.py
@@ -32,6 +32,7 @@ from webob import Request, Response
 
 from allura import model as M
 from alluratest.controller import setup_unit_test
+from io import open
 
 
 class File(M.File):
diff --git a/Allura/allura/tests/test_globals.py b/Allura/allura/tests/test_globals.py
index 70acceb..2c278db 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -49,6 +49,7 @@ from allura.tests import decorators as td
 
 from forgewiki import model as WM
 from forgeblog import model as BM
+from io import open
 
 
 def squish_spaces(text):
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index 92a9011..b49be5f 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -44,6 +44,7 @@ from allura.lib.security import Credentials
 from allura.tests import decorators as td
 from alluratest.controller import setup_basic_test
 import six
+from io import open
 
 
 def setUp(self):
diff --git a/Allura/ldap-setup.py b/Allura/ldap-setup.py
index fcd79ce..07dbe29 100644
--- a/Allura/ldap-setup.py
+++ b/Allura/ldap-setup.py
@@ -26,6 +26,7 @@ import logging
 from contextlib import contextmanager
 from tempfile import mkstemp
 from six.moves.configparser import ConfigParser, NoOptionError
+from io import open
 
 logging.basicConfig(level=logging.DEBUG)
 log = logging.getLogger('ldap-setup')
diff --git a/Allura/ldap-userconfig.py b/Allura/ldap-userconfig.py
index 63334b5..c0f2330 100644
--- a/Allura/ldap-userconfig.py
+++ b/Allura/ldap-userconfig.py
@@ -23,6 +23,7 @@ import os
 import sys
 import pwd
 import grp
+from io import open
 
 
 def main():
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
index 4a6f38b..a7d80e8 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
@@ -44,6 +44,7 @@ from allura.lib import helpers as h
 from allura.tests import decorators as td
 
 from forgediscussion import model as FM
+from io import open
 
 log = logging.getLogger(__name__)
 
diff --git a/ForgeGit/forgegit/model/git_repo.py b/ForgeGit/forgegit/model/git_repo.py
index cf829f4..2c01380 100644
--- a/ForgeGit/forgegit/model/git_repo.py
+++ b/ForgeGit/forgegit/model/git_repo.py
@@ -40,6 +40,7 @@ from ming.utils import LazyProperty
 from allura.lib import helpers as h
 from allura.model.repository import topological_sort, prefix_paths_union
 from allura import model as M
+from io import open
 
 log = logging.getLogger(__name__)
 
diff --git a/ForgeGit/forgegit/tests/functional/test_controllers.py b/ForgeGit/forgegit/tests/functional/test_controllers.py
index 40ddef2..e25a961 100644
--- a/ForgeGit/forgegit/tests/functional/test_controllers.py
+++ b/ForgeGit/forgegit/tests/functional/test_controllers.py
@@ -45,6 +45,7 @@ from allura.tests.test_globals import squish_spaces
 from forgegit.tests import with_git
 from forgegit import model as GM
 import six
+from io import open
 
 
 class _TestCase(TestController):
diff --git a/ForgeGit/forgegit/tests/model/test_repository.py b/ForgeGit/forgegit/tests/model/test_repository.py
index a89624f..30672f3 100644
--- a/ForgeGit/forgegit/tests/model/test_repository.py
+++ b/ForgeGit/forgegit/tests/model/test_repository.py
@@ -48,6 +48,7 @@ from allura.webhooks import RepoPushWebhookSender
 from forgegit import model as GM
 from forgegit.tests import with_git
 from forgewiki import model as WM
+from io import open
 
 
 class TestNewGit(unittest.TestCase):
diff --git a/ForgeImporters/forgeimporters/base.py b/ForgeImporters/forgeimporters/base.py
index deb96ed..edf6aac 100644
--- a/ForgeImporters/forgeimporters/base.py
+++ b/ForgeImporters/forgeimporters/base.py
@@ -26,6 +26,7 @@ from collections import defaultdict
 import traceback
 from six.moves.urllib.parse import urlparse
 from datetime import datetime
+from io import open
 try:
     from cStringIO import StringIO
 except ImportError:
diff --git a/ForgeImporters/forgeimporters/forge/tracker.py b/ForgeImporters/forgeimporters/forge/tracker.py
index 19638b1..b5825ab 100644
--- a/ForgeImporters/forgeimporters/forge/tracker.py
+++ b/ForgeImporters/forgeimporters/forge/tracker.py
@@ -50,6 +50,7 @@ from forgeimporters.base import (
     get_importer_upload_path,
     save_importer_upload,
 )
+from io import open
 
 
 class ForgeTrackerImportForm(ToolImportForm):
diff --git a/ForgeImporters/forgeimporters/trac/tests/test_tickets.py b/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
index bf3be44..b58e122 100644
--- a/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
+++ b/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
@@ -38,6 +38,7 @@ from forgeimporters.trac.tickets import (
     TracTicketImportController,
     TracImportSupport,
 )
+from io import open
 
 
 class TestTracTicketImporter(TestCase):
diff --git a/ForgeSVN/forgesvn/model/svn.py b/ForgeSVN/forgesvn/model/svn.py
index d413ee8..7bf084b 100644
--- a/ForgeSVN/forgesvn/model/svn.py
+++ b/ForgeSVN/forgesvn/model/svn.py
@@ -47,6 +47,7 @@ from allura.lib import helpers as h
 from allura.model.auth import User
 from allura.model.repository import zipdir
 from allura.model import repository as RM
+from io import open
 
 log = logging.getLogger(__name__)
 
diff --git a/ForgeSVN/forgesvn/tests/model/test_repository.py b/ForgeSVN/forgesvn/tests/model/test_repository.py
index 59c3bfb..76e97ec 100644
--- a/ForgeSVN/forgesvn/tests/model/test_repository.py
+++ b/ForgeSVN/forgesvn/tests/model/test_repository.py
@@ -51,6 +51,7 @@ from forgesvn.model.svn import svn_path_exists
 from forgesvn.tests import with_svn
 from allura.tests.decorators import with_tool
 import six
+from io import open
 
 
 class TestNewRepo(unittest.TestCase):
diff --git a/ForgeWiki/forgewiki/tests/test_app.py b/ForgeWiki/forgewiki/tests/test_app.py
index 6bfb224..bd58982 100644
--- a/ForgeWiki/forgewiki/tests/test_app.py
+++ b/ForgeWiki/forgewiki/tests/test_app.py
@@ -32,6 +32,7 @@ from allura import model as M
 from allura.tests import decorators as td
 from alluratest.controller import setup_basic_test, setup_global_objects
 from forgewiki import model as WM
+from io import open
 
 
 class TestBulkExport(object):
diff --git a/fuse/accessfs.py b/fuse/accessfs.py
index ee19ba1..2a2a7f8 100644
--- a/fuse/accessfs.py
+++ b/fuse/accessfs.py
@@ -36,6 +36,7 @@ from collections import deque
 
 import fuse
 import six
+from io import open
 
 log = logging.getLogger(__name__)
 
diff --git a/scripts/perf/call_count.py b/scripts/perf/call_count.py
index 2b3e1ce..baf7d95 100755
--- a/scripts/perf/call_count.py
+++ b/scripts/perf/call_count.py
@@ -38,6 +38,7 @@ from allura.tests import TestController
 from allura.tests.decorators import patch_middleware_config
 
 from forgewiki import model as WM
+from io import open
 
 
 def parse_args():
diff --git a/scripts/project-import.py b/scripts/project-import.py
index 2ca0f23..a83ed48 100644
--- a/scripts/project-import.py
+++ b/scripts/project-import.py
@@ -34,6 +34,7 @@ from allura import model as M
 from allura.lib import helpers as h
 from allura.lib.plugin import ProjectRegistrationProvider
 import six
+from io import open
 
 log = logging.getLogger(__name__)
 
diff --git a/scripts/teamforge-import.py b/scripts/teamforge-import.py
index 8c2ba90..5789179 100644
--- a/scripts/teamforge-import.py
+++ b/scripts/teamforge-import.py
@@ -45,6 +45,7 @@ from allura import model as M
 from allura.lib import helpers as h
 from allura.lib import utils
 import six
+from io import open
 
 log = logging.getLogger('teamforge-import')
 
diff --git a/scripts/trac_export_wiki.py b/scripts/trac_export_wiki.py
index 321e4ed..d698c04 100755
--- a/scripts/trac_export_wiki.py
+++ b/scripts/trac_export_wiki.py
@@ -23,6 +23,7 @@ import sys
 from optparse import OptionParser
 
 from tracwikiimporter.scripts.wiki_from_trac.extractors import WikiExporter
+from io import open
 
 
 def parse_options():
diff --git a/scripts/trac_import.py b/scripts/trac_import.py
index 10db3cf..ef4806d 100644
--- a/scripts/trac_import.py
+++ b/scripts/trac_import.py
@@ -24,6 +24,7 @@ from optparse import OptionParser
 from allura.lib.import_api import AlluraImportApiClient
 from tracwikiimporter.scripts.wiki_from_trac.loaders import import_wiki
 import six
+from io import open
 
 
 def main():
diff --git a/scripts/wiki-copy.py b/scripts/wiki-copy.py
index 6182d68..383f0e7 100644
--- a/scripts/wiki-copy.py
+++ b/scripts/wiki-copy.py
@@ -30,6 +30,7 @@ import json
 from six.moves.configparser import ConfigParser, NoOptionError
 import webbrowser
 import oauth2 as oauth
+from io import open
 
 
 def main():


[allura] 05/41: Misc: small trac import unicode fix; unlikely to be completely functional yet

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 8fc58ab7367a7fbef21904d1b8a719449104a88f
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 12:07:17 2020 -0500

    Misc: small trac import unicode fix; unlikely to be completely functional yet
---
 Allura/allura/scripts/trac_export.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Allura/allura/scripts/trac_export.py b/Allura/allura/scripts/trac_export.py
index d05b68b..19ec460 100644
--- a/Allura/allura/scripts/trac_export.py
+++ b/Allura/allura/scripts/trac_export.py
@@ -255,7 +255,7 @@ class TracExport(object):
         except urllib2.HTTPError, e:
             if 'emulated' in e.msg:
                 body = e.fp.read()
-                if 'beyond the number of pages in the query' in body or 'Log in with a SourceForge account' in body:
+                if 'beyond the number of pages in the query' in six.ensure_text(body):
                     raise StopIteration
             raise
         reader = csv.reader(f)
@@ -263,8 +263,8 @@ class TracExport(object):
         for r in reader:
             if r and r[0].isdigit():
                 id = int(r[0])
-                extra = {'date': self.trac2z_date(
-                    r[1]), 'date_updated': self.trac2z_date(r[2])}
+                extra = {'date': self.trac2z_date(r[1]),
+                         'date_updated': self.trac2z_date(r[2])}
                 res.append((id, extra))
         self.page += 1
 


[allura] 12/41: [#8349] python-modernize -n -w --no-diffs -f next .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit ae1d87ea30034a7d986b2f10f1b8b02107eb8cde
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 13:30:45 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f next .
---
 Allura/allura/lib/spam/stopforumspamfilter.py     |  2 +-
 Allura/allura/model/project.py                    |  4 ++--
 Allura/allura/model/repo_refresh.py               |  2 +-
 Allura/allura/model/repository.py                 |  6 +++---
 Allura/allura/scripts/trac_export.py              |  6 +++---
 Allura/allura/tests/functional/test_site_admin.py |  6 +++---
 Allura/allura/tests/test_helpers.py               |  2 +-
 ForgeGit/forgegit/tests/model/test_repository.py  |  2 +-
 ForgeSVN/forgesvn/tests/model/test_repository.py  | 16 ++++++++--------
 scripts/rethumb.py                                |  2 +-
 10 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/Allura/allura/lib/spam/stopforumspamfilter.py b/Allura/allura/lib/spam/stopforumspamfilter.py
index 09bdba6..24d040f 100644
--- a/Allura/allura/lib/spam/stopforumspamfilter.py
+++ b/Allura/allura/lib/spam/stopforumspamfilter.py
@@ -56,7 +56,7 @@ class StopForumSpamSpamFilter(SpamFilter):
                     self.packed_ips.add(ip_int)
         # to get actual memory usage, use: from pympler.asizeof import asizeof
         log.info('Read stopforumspam file; %s recs, probably %s bytes stored in memory', len(self.packed_ips),
-                 len(self.packed_ips) * getsizeof(iter(self.packed_ips).next()) * 2)
+                 len(self.packed_ips) * getsizeof(next(iter(self.packed_ips))) * 2)
 
     def check(self, text, artifact=None, user=None, content_type='comment', **kw):
         ip = utils.ip_address(request)
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index 49b3dbe..4bd97ad 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -1054,8 +1054,8 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
 
     def social_account(self, socialnetwork):
         try:
-            account = (
-                sn for sn in self.socialnetworks if sn.socialnetwork == socialnetwork).next()
+            account = next((
+                sn for sn in self.socialnetworks if sn.socialnetwork == socialnetwork))
         except StopIteration:
             return None
         else:
diff --git a/Allura/allura/model/repo_refresh.py b/Allura/allura/model/repo_refresh.py
index 86edbd8..c5a1824 100644
--- a/Allura/allura/model/repo_refresh.py
+++ b/Allura/allura/model/repo_refresh.py
@@ -71,7 +71,7 @@ def refresh_repo(repo, all_commits=False, notify=True, new_clone=False, commits_
 
     # Refresh child references
     for i, oid in enumerate(commit_ids):
-        ci = CommitDoc.m.find(dict(_id=oid), validate=False).next()
+        ci = next(CommitDoc.m.find(dict(_id=oid), validate=False))
         refresh_children(ci)
         if (i + 1) % 100 == 0:
             log.info('Refresh child info %d for parents of %s',
diff --git a/Allura/allura/model/repository.py b/Allura/allura/model/repository.py
index 4a951d0..790690d 100644
--- a/Allura/allura/model/repository.py
+++ b/Allura/allura/model/repository.py
@@ -1558,7 +1558,7 @@ class LastCommit(RepoObject):
             # on the top-level dir, the relevant commit should always be the current commit
             return commit._id
         try:
-            rev = commit.repo.log(commit._id, path, id_only=True, limit=1).next()
+            rev = next(commit.repo.log(commit._id, path, id_only=True, limit=1))
             return commit.repo.rev_to_commit_id(rev)
         except StopIteration:
             log.error('Tree node not recognized by SCM: %s @ %s',
@@ -1574,8 +1574,8 @@ class LastCommit(RepoObject):
             return lcid_cache[path]
         try:
             log_iter = commit.repo.log(commit._id, path, id_only=True, limit=2)
-            log_iter.next()
-            rev = log_iter.next()
+            next(log_iter)
+            rev = next(log_iter)
             return commit.repo.rev_to_commit_id(rev)
         except StopIteration:
             return None
diff --git a/Allura/allura/scripts/trac_export.py b/Allura/allura/scripts/trac_export.py
index ecadac5..4cb4347 100644
--- a/Allura/allura/scripts/trac_export.py
+++ b/Allura/allura/scripts/trac_export.py
@@ -155,7 +155,7 @@ class TracExport(object):
         url = self.full_url(self.TICKET_URL % id, 'csv')
         f = self.csvopen(url)
         reader = csv.DictReader(f)
-        ticket_fields = reader.next()
+        ticket_fields = next(reader)
         ticket_fields['class'] = 'ARTIFACT'
         ticket = self.remap_fields(ticket_fields)
 
@@ -228,7 +228,7 @@ class TracExport(object):
         url = self.full_url(self.QUERY_MAX_ID_URL, 'csv')
         f = self.csvopen(url)
         reader = csv.DictReader(f)
-        fields = reader.next()
+        fields = next(reader)
         print(fields)
         return int(fields['id'])
 
@@ -261,7 +261,7 @@ class TracExport(object):
                     raise StopIteration
             raise
         reader = csv.reader(f)
-        cols = reader.next()
+        cols = next(reader)
         for r in reader:
             if r and r[0].isdigit():
                 id = int(r[0])
diff --git a/Allura/allura/tests/functional/test_site_admin.py b/Allura/allura/tests/functional/test_site_admin.py
index f5ce746..ac0e195 100644
--- a/Allura/allura/tests/functional/test_site_admin.py
+++ b/Allura/allura/tests/functional/test_site_admin.py
@@ -169,7 +169,7 @@ class TestSiteAdmin(TestController):
             user='root',
             path='/p/test/admin',
         ), status=302)
-        task = M.MonQTask.query.find({}).sort('_id', -1).next()
+        task = next(M.MonQTask.query.find({}).sort('_id', -1))
         assert str(task._id) in r.location
         assert task.context['project_id'] == project._id
         assert task.context['app_config_id'] == app.config._id
@@ -249,7 +249,7 @@ class TestSiteAdminNotifications(TestController):
             user_role=user_role,
             page_regex=page_regex,
             page_tool_type=page_tool_type))
-        note = M.notification.SiteNotification.query.find().sort('_id', -1).next()
+        note = next(M.notification.SiteNotification.query.find().sort('_id', -1))
 
         assert '/nf/admin/site_notifications' in r.location
 
@@ -312,7 +312,7 @@ class TestSiteAdminNotifications(TestController):
             page_tool_type=page_tool_type))
         ThreadLocalORMSession().flush_all()
 
-        note = M.notification.SiteNotification.query.find().sort('_id', -1).next()
+        note = next(M.notification.SiteNotification.query.find().sort('_id', -1))
 
         assert '/nf/admin/site_notifications' in r.location
         assert M.notification.SiteNotification.query.find().count() == count
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index bf1d5e0..92a9011 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -115,7 +115,7 @@ def test_find_project():
 def test_make_roles():
     h.set_context('test', 'wiki', neighborhood='Projects')
     pr = M.ProjectRole.anonymous()
-    assert h.make_roles([pr._id]).next() == pr
+    assert next(h.make_roles([pr._id])) == pr
 
 
 @td.with_wiki
diff --git a/ForgeGit/forgegit/tests/model/test_repository.py b/ForgeGit/forgegit/tests/model/test_repository.py
index a80d9b8..0b6fe5c 100644
--- a/ForgeGit/forgegit/tests/model/test_repository.py
+++ b/ForgeGit/forgegit/tests/model/test_repository.py
@@ -1158,5 +1158,5 @@ class TestGitRename(unittest.TestCase):
 
     def test_merge_commit(self):
         merge_sha = '13951944969cf45a701bf90f83647b309815e6d5'
-        commit = self.repo.log(revs=merge_sha, id_only=False).next()
+        commit = next(self.repo.log(revs=merge_sha, id_only=False))
         self.assertEqual(commit['rename_details'], {})
diff --git a/ForgeSVN/forgesvn/tests/model/test_repository.py b/ForgeSVN/forgesvn/tests/model/test_repository.py
index 8f18ad4..59c3bfb 100644
--- a/ForgeSVN/forgesvn/tests/model/test_repository.py
+++ b/ForgeSVN/forgesvn/tests/model/test_repository.py
@@ -359,7 +359,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
         assert not self.repo.is_file('/a')
 
     def test_paged_diffs(self):
-        entry = self.repo.commit(self.repo.log(2, id_only=True, limit=1).next())
+        entry = self.repo.commit(next(self.repo.log(2, id_only=True, limit=1)))
         self.assertEqual(entry.diffs, entry.paged_diffs())
         self.assertEqual(entry.diffs, entry.paged_diffs(start=0))
         added_expected = entry.diffs.added[1:3]
@@ -374,14 +374,14 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
         self.assertEqual(sorted(actual.keys()), sorted(empty.keys()))
 
     def test_diff_create_file(self):
-        entry = self.repo.commit(self.repo.log(1, id_only=True, limit=1).next())
+        entry = self.repo.commit(next(self.repo.log(1, id_only=True, limit=1)))
         self.assertEqual(
             entry.diffs, dict(
                 copied=[], changed=[], renamed=[],
                 removed=[], added=['/README'], total=1))
 
     def test_diff_create_path(self):
-        entry = self.repo.commit(self.repo.log(2, id_only=True, limit=1).next())
+        entry = self.repo.commit(next(self.repo.log(2, id_only=True, limit=1)))
         actual = entry.diffs
         actual.added = sorted(actual.added)
         self.assertEqual(
@@ -392,21 +392,21 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
                     '/a/b/c/hello.txt']), total=4))
 
     def test_diff_modify_file(self):
-        entry = self.repo.commit(self.repo.log(3, id_only=True, limit=1).next())
+        entry = self.repo.commit(next(self.repo.log(3, id_only=True, limit=1)))
         self.assertEqual(
             entry.diffs, dict(
                 copied=[], changed=['/README'], renamed=[],
                 removed=[], added=[], total=1))
 
     def test_diff_delete(self):
-        entry = self.repo.commit(self.repo.log(4, id_only=True, limit=1).next())
+        entry = self.repo.commit(next(self.repo.log(4, id_only=True, limit=1)))
         self.assertEqual(
             entry.diffs, dict(
                 copied=[], changed=[], renamed=[],
                 removed=['/a/b/c/hello.txt'], added=[], total=1))
 
     def test_diff_copy(self):
-        entry = self.repo.commit(self.repo.log(5, id_only=True, limit=1).next())
+        entry = self.repo.commit(next(self.repo.log(5, id_only=True, limit=1)))
         assert_equals(dict(entry.diffs), dict(
                 copied=[{'new': '/b', 'old': '/a', 'ratio': 1}],  renamed=[],
                 changed=[], removed=[], added=[], total=1))
@@ -656,11 +656,11 @@ class _Test(unittest.TestCase):
         for k, v in six.iteritems(kwargs):
             if isinstance(v, basestring):
                 obj = M.repository.Blob(
-                    t, k, self.idgen.next())
+                    t, k, next(self.idgen))
                 t.blob_ids.append(Object(
                     name=k, id=obj._id))
             else:
-                obj = self._make_tree(self.idgen.next(), **v)
+                obj = self._make_tree(next(self.idgen), **v)
                 t.tree_ids.append(Object(
                     name=k, id=obj._id))
         session(t).flush()
diff --git a/scripts/rethumb.py b/scripts/rethumb.py
index 7a3d61a..715c199 100644
--- a/scripts/rethumb.py
+++ b/scripts/rethumb.py
@@ -119,7 +119,7 @@ class RethumbCommand(base.Command):
 
                 # Otherwise, we'll take attachment classes belonging to app's
                 # package
-                ep = iter_entry_points('allura', app.tool_name).next()
+                ep = next(iter_entry_points('allura', app.tool_name))
                 app_package = ep.module_name.split('.', 1)[0]
                 if app_package == 'allura':
                     # Apps in allura known to not define own attachment types


[allura] 28/41: [#8349] python-modernize -n -w --no-diffs -f metaclass .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 423d003966285d1e830a9f898f1ec5741ae6753f
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 15:18:56 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f metaclass .
---
 Allura/allura/controllers/discuss.py  | 12 ++++--------
 Allura/allura/webhooks.py             |  3 +--
 ForgeImporters/forgeimporters/base.py |  7 +++----
 3 files changed, 8 insertions(+), 14 deletions(-)

diff --git a/Allura/allura/controllers/discuss.py b/Allura/allura/controllers/discuss.py
index f2ac57b..d6fa61e 100644
--- a/Allura/allura/controllers/discuss.py
+++ b/Allura/allura/controllers/discuss.py
@@ -149,8 +149,7 @@ class AppDiscussionController(DiscussionController):
             app_config_id=c.app.config._id)
 
 
-class ThreadsController(BaseController):
-    __metaclass__ = h.ProxiedAttrMeta
+class ThreadsController(six.with_metaclass(h.ProxiedAttrMeta, BaseController)):
     M = h.attrproxy('_discussion_controller', 'M')
     W = h.attrproxy('_discussion_controller', 'W')
     ThreadController = h.attrproxy(
@@ -171,8 +170,7 @@ class ThreadsController(BaseController):
             raise exc.HTTPNotFound()
 
 
-class ThreadController(BaseController, FeedController):
-    __metaclass__ = h.ProxiedAttrMeta
+class ThreadController(six.with_metaclass(h.ProxiedAttrMeta, BaseController, FeedController)):
     M = h.attrproxy('_discussion_controller', 'M')
     W = h.attrproxy('_discussion_controller', 'W')
     ThreadController = h.attrproxy(
@@ -280,8 +278,7 @@ def handle_post_or_reply(thread, edit_widget, rate_limit, kw, parent_post_id=Non
     redirect(request.referer or '/')
 
 
-class PostController(BaseController):
-    __metaclass__ = h.ProxiedAttrMeta
+class PostController(six.with_metaclass(h.ProxiedAttrMeta, BaseController)):
     M = h.attrproxy('_discussion_controller', 'M')
     W = h.attrproxy('_discussion_controller', 'W')
     ThreadController = h.attrproxy(
@@ -472,8 +469,7 @@ class DiscussionAttachmentsController(AttachmentsController):
     AttachmentControllerClass = DiscussionAttachmentController
 
 
-class ModerationController(BaseController):
-    __metaclass__ = h.ProxiedAttrMeta
+class ModerationController(six.with_metaclass(h.ProxiedAttrMeta, BaseController)):
     PostModel = M.Post
     M = h.attrproxy('_discussion_controller', 'M')
     W = h.attrproxy('_discussion_controller', 'W')
diff --git a/Allura/allura/webhooks.py b/Allura/allura/webhooks.py
index dfa6247..dafb5ce 100644
--- a/Allura/allura/webhooks.py
+++ b/Allura/allura/webhooks.py
@@ -102,8 +102,7 @@ class WebhookControllerMeta(type):
         return type.__call__(cls, sender, app, *args, **kw)
 
 
-class WebhookController(BaseController, AdminControllerMixin):
-    __metaclass__ = WebhookControllerMeta
+class WebhookController(six.with_metaclass(WebhookControllerMeta, BaseController, AdminControllerMixin)):
     create_form = WebhookCreateForm
     edit_form = WebhookEditForm
 
diff --git a/ForgeImporters/forgeimporters/base.py b/ForgeImporters/forgeimporters/base.py
index 4578d95..14ceeb1 100644
--- a/ForgeImporters/forgeimporters/base.py
+++ b/ForgeImporters/forgeimporters/base.py
@@ -28,6 +28,7 @@ from six.moves.urllib.parse import urlparse
 from datetime import datetime
 from io import open
 from six.moves import filter
+import six
 try:
     from cStringIO import StringIO
 except ImportError:
@@ -354,11 +355,10 @@ class ToolImportControllerMeta(type):
         return type.__call__(cls, importer, *args, **kw)
 
 
-class ToolImportController(BaseController):
+class ToolImportController(six.with_metaclass(ToolImportControllerMeta, BaseController)):
     """ Base class for ToolImporter controllers.
 
     """
-    __metaclass__ = ToolImportControllerMeta
 
     def __init__(self, importer):
         """
@@ -395,7 +395,7 @@ class ToolImporterMeta(type):
         return type.__call__(cls, *args, **kw)
 
 
-class ToolImporter(object):
+class ToolImporter(six.with_metaclass(ToolImporterMeta, object)):
 
     """
     Base class for tool importers.
@@ -431,7 +431,6 @@ class ToolImporter(object):
        The controller for this importer, to handle single tool imports.
 
     """
-    __metaclass__ = ToolImporterMeta
 
     target_app = None  # app or list of apps
     source = None  # string description of source, must match project importer


[allura] 30/41: [#8349] python-modernize -n -w --no-diffs -f exec .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 78c4372f7fd1a84c70d0a7ba70491206427ad6a3
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 15:21:55 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f exec .
---
 Allura/allura/command/script.py | 2 +-
 Allura/setup.py                 | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Allura/allura/command/script.py b/Allura/allura/command/script.py
index ee15316..fd59d82 100644
--- a/Allura/allura/command/script.py
+++ b/Allura/allura/command/script.py
@@ -67,7 +67,7 @@ class ScriptCommand(base.Command):
                     cProfile.run(fp, '%s.profile' %
                                  os.path.basename(self.args[1]))
                 else:
-                    exec fp.read() in ns
+                    exec(fp.read(), ns)
 
 
 class SetToolAccessCommand(base.Command):
diff --git a/Allura/setup.py b/Allura/setup.py
index 441d51a..48c2b4e 100644
--- a/Allura/setup.py
+++ b/Allura/setup.py
@@ -21,7 +21,7 @@ from __future__ import unicode_literals
 from __future__ import absolute_import
 from setuptools import setup, find_packages
 
-exec open('allura/version.py').read()
+exec(open('allura/version.py').read())
 
 PROJECT_DESCRIPTION = '''
 Allura is an open source implementation of a software "forge", a web site


[allura] 34/41: [#8349] python-modernize -n -w --no-diffs -f file .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 487829a9aed0b9398b5caa78869337aa11e47072
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 15:35:04 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f file .
---
 Allura/allura/tests/functional/test_admin.py            |  6 +++---
 Allura/allura/tests/functional/test_home.py             |  2 +-
 Allura/allura/tests/functional/test_neighborhood.py     |  4 ++--
 ForgeTracker/forgetracker/tests/functional/test_root.py | 16 ++++++++--------
 ForgeWiki/forgewiki/tests/functional/test_rest.py       |  2 +-
 ForgeWiki/forgewiki/tests/functional/test_root.py       | 10 +++++-----
 6 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/Allura/allura/tests/functional/test_admin.py b/Allura/allura/tests/functional/test_admin.py
index 6db9053..a55b062 100644
--- a/Allura/allura/tests/functional/test_admin.py
+++ b/Allura/allura/tests/functional/test_admin.py
@@ -372,7 +372,7 @@ class TestProjectAdmin(TestController):
         file_name = 'neo-icon-set-454545-256x350.png'
         file_path = os.path.join(
             allura.__path__[0], 'nf', 'allura', 'images', file_name)
-        file_data = file(file_path).read()
+        file_data = open(file_path).read()
         upload = ('icon', file_name, file_data)
 
         self.app.get('/admin/')
@@ -396,7 +396,7 @@ class TestProjectAdmin(TestController):
         file_name = 'neo-icon-set-454545-256x350.png'
         file_path = os.path.join(
             allura.__path__[0], 'nf', 'allura', 'images', file_name)
-        file_data = file(file_path).read()
+        file_data = open(file_path).read()
         upload = ('screenshot', file_name, file_data)
 
         self.app.get('/admin/')
@@ -436,7 +436,7 @@ class TestProjectAdmin(TestController):
         for file_name in ('admin_24.png', 'admin_32.png'):
             file_path = os.path.join(allura.__path__[0], 'nf', 'allura',
                                      'images', file_name)
-            file_data = file(file_path).read()
+            file_data = open(file_path).read()
             upload = ('screenshot', file_name, file_data)
             self.app.post('/admin/add_screenshot', params=dict(
                 caption=file_name),
diff --git a/Allura/allura/tests/functional/test_home.py b/Allura/allura/tests/functional/test_home.py
index dc523c2..6955a67 100644
--- a/Allura/allura/tests/functional/test_home.py
+++ b/Allura/allura/tests/functional/test_home.py
@@ -157,7 +157,7 @@ class TestProjectHome(TestController):
     def test_user_icon(self):
         file_name = 'neo-icon-set-454545-256x350.png'
         file_path = os.path.join(allura.__path__[0], 'nf', 'allura', 'images', file_name)
-        file_data = file(file_path).read()
+        file_data = open(file_path).read()
         upload = ('icon', file_name, file_data)
         with td.audits('update project icon'):
             self.app.post('/u/test-admin/admin/update', params=dict(
diff --git a/Allura/allura/tests/functional/test_neighborhood.py b/Allura/allura/tests/functional/test_neighborhood.py
index ce23cbe..672662c 100644
--- a/Allura/allura/tests/functional/test_neighborhood.py
+++ b/Allura/allura/tests/functional/test_neighborhood.py
@@ -266,7 +266,7 @@ class TestNeighborhood(TestController):
         file_name = 'neo-icon-set-454545-256x350.png'
         file_path = os.path.join(
             allura.__path__[0], 'nf', 'allura', 'images', file_name)
-        file_data = file(file_path).read()
+        file_data = open(file_path).read()
         upload = ('icon', file_name, file_data)
 
         r = self.app.get('/adobe/_admin/', extra_environ=dict(username=str('root')))
@@ -869,7 +869,7 @@ class TestNeighborhood(TestController):
         file_name = 'adobe_icon.png'
         file_path = os.path.join(
             allura.__path__[0], 'public', 'nf', 'images', file_name)
-        file_data = file(file_path).read()
+        file_data = open(file_path).read()
         upload = ('icon', file_name, file_data)
 
         r = self.app.get('/adobe/_admin/awards',
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index 32b3942..c8e7ae1 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -880,7 +880,7 @@ class TestFunctionalController(TrackerTestController):
 
     def test_new_attachment(self):
         file_name = 'test_root.py'
-        file_data = file(__file__).read()
+        file_data = open(__file__).read()
         upload = ('attachment', file_name, file_data)
         self.new_ticket(summary='test new attachment')
         ticket_editor = self.app.post('/bugs/1/update_ticket', {
@@ -895,7 +895,7 @@ class TestFunctionalController(TrackerTestController):
 
     def test_delete_attachment(self):
         file_name = 'test_root.py'
-        file_data = file(__file__).read()
+        file_data = open(__file__).read()
         upload = ('attachment', file_name, file_data)
         self.new_ticket(summary='test new attachment')
         ticket_editor = self.app.post('/bugs/1/update_ticket', {
@@ -940,7 +940,7 @@ class TestFunctionalController(TrackerTestController):
 
     def test_new_text_attachment_content(self):
         file_name = 'test_root.py'
-        file_data = file(__file__).read()
+        file_data = open(__file__).read()
         upload = ('attachment', file_name, file_data)
         self.new_ticket(summary='test new attachment')
         ticket_editor = self.app.post('/bugs/1/update_ticket', {
@@ -953,7 +953,7 @@ class TestFunctionalController(TrackerTestController):
     def test_two_attachments(self):
         file_name1 = 'test_root1.py'
         file_name2 = 'test_root2.py'
-        file_data = file(__file__).read()
+        file_data = open(__file__).read()
         self.new_ticket(summary='test new attachment')
         ticket_editor = self.app.post('/bugs/1/update_ticket', {
             'summary': 'zzz'
@@ -967,7 +967,7 @@ class TestFunctionalController(TrackerTestController):
         file_name = 'neo-icon-set-454545-256x350.png'
         file_path = os.path.join(
             allura.__path__[0], 'nf', 'allura', 'images', file_name)
-        file_data = file(file_path).read()
+        file_data = open(file_path).read()
         upload = ('attachment', file_name, file_data)
         self.new_ticket(summary='test new attachment')
         self.app.post('/bugs/1/update_ticket', {
@@ -1672,7 +1672,7 @@ class TestFunctionalController(TrackerTestController):
 
     def test_new_ticket_notification_contains_attachments(self):
         file_name = 'tést_root.py'.encode('utf-8')
-        file_data = file(__file__).read()
+        file_data = open(__file__).read()
         upload = ('ticket_form.attachment', file_name, file_data)
         r = self.app.post('/bugs/save_ticket', {
             'ticket_form.summary': 'new ticket with attachment'
@@ -2366,7 +2366,7 @@ class TestFunctionalController(TrackerTestController):
         file_name = 'neo-icon-set-454545-256x350.png'
         file_path = os.path.join(
             allura.__path__[0], 'nf', 'allura', 'images', file_name)
-        file_data = file(file_path).read()
+        file_data = open(file_path).read()
         upload = ('attachment', file_name, file_data)
         self.new_ticket(summary='test move attachment')
 
@@ -2466,7 +2466,7 @@ class TestFunctionalController(TrackerTestController):
                      11)
 
         file_name = 'test_root.py'
-        file_data = file(__file__).read()
+        file_data = open(__file__).read()
         upload = ('attachment', file_name, file_data)
         r = self.app.post('/bugs/1/update_ticket', {
             'summary': 'test rest attach'
diff --git a/ForgeWiki/forgewiki/tests/functional/test_rest.py b/ForgeWiki/forgewiki/tests/functional/test_rest.py
index e29375d..70e08ca 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_rest.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_rest.py
@@ -48,7 +48,7 @@ class TestWikiApi(TestRestApiBase):
     def test_get_page(self):
         r = self.app.get('/p/test/wiki/Home/')
         discussion_url = r.html.find('form', id='edit_post')['action'][:-4]
-        content = file(__file__).read()
+        content = open(__file__).read()
         self.app.post('/wiki/Home/attach',
                       upload_files=[('file_info', 'test_root.py', content)])
         r = self.app.get('/rest/p/test/wiki/Home/')
diff --git a/ForgeWiki/forgewiki/tests/functional/test_root.py b/ForgeWiki/forgewiki/tests/functional/test_root.py
index f917c1e..b41ae5e 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_root.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_root.py
@@ -494,7 +494,7 @@ class TestRootController(TestController):
                 'text': 'sometext',
                 'labels': '',
                 })
-        content = file(__file__).read()
+        content = open(__file__).read()
         self.app.post(h.urlquote('/wiki/tést/attach'),
                       upload_files=[('file_info', 'test_root.py', content)])
         response = self.app.get(h.urlquote('/wiki/tést/'))
@@ -508,7 +508,7 @@ class TestRootController(TestController):
                 'text': 'sometext',
                 'labels': '',
                 })
-        content = file(__file__).read()
+        content = open(__file__).read()
         self.app.post(h.urlquote('/wiki/tést/attach'),
                       upload_files=[('file_info', 'test1.py', content), ('file_info', 'test2.py', content)])
         response = self.app.get(h.urlquote('/wiki/tést/'))
@@ -524,7 +524,7 @@ class TestRootController(TestController):
                 'labels': '',
                 })
         file_name = 'test_root.py'
-        file_data = file(__file__).read()
+        file_data = open(__file__).read()
         upload = ('file_info', file_name, file_data)
         self.app.post(h.urlquote('/wiki/tést/attach'), upload_files=[upload])
         page_editor = self.app.get(h.urlquote('/wiki/tést/edit'))
@@ -540,7 +540,7 @@ class TestRootController(TestController):
         file_name = 'neo-icon-set-454545-256x350.png'
         file_path = os.path.join(
             allura.__path__[0], 'nf', 'allura', 'images', file_name)
-        file_data = file(file_path).read()
+        file_data = open(file_path).read()
         upload = ('file_info', file_name, file_data)
         self.app.post('/wiki/TEST/attach', upload_files=[upload])
         h.set_context('test', 'wiki', neighborhood='Projects')
@@ -713,7 +713,7 @@ class TestRootController(TestController):
             'labels': '',
             }
         self.app.post('/wiki/TEST/update', params=params)
-        content = file(__file__).read()
+        content = open(__file__).read()
         self.app.post('/wiki/TEST/attach',
                       upload_files=[('file_info', 'test_root.py', content)])
         r = self.app.get('/wiki/TEST/')


[allura] 04/41: Misc: avoid errors when invalid page param

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 02657c5591d9b0aa4182dcfe803cc43144b776f1
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 11:51:53 2020 -0500

    Misc: avoid errors when invalid page param
---
 Allura/allura/lib/app_globals.py    | 5 ++++-
 Allura/allura/tests/test_globals.py | 3 +++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/Allura/allura/lib/app_globals.py b/Allura/allura/lib/app_globals.py
index 05e284f..b16190a 100644
--- a/Allura/allura/lib/app_globals.py
+++ b/Allura/allura/lib/app_globals.py
@@ -383,7 +383,10 @@ class Globals(object):
         limit = self.manage_paging_preference(limit, default)
         limit = max(int(limit), 1)
         limit = min(limit, asint(config.get('limit_param_max', 500)))
-        page = max(int(page), 0)
+        try:
+            page = max(int(page), 0)
+        except ValueError:
+            page = 0
         start = page * int(limit)
         return (limit, page, start)
 
diff --git a/Allura/allura/tests/test_globals.py b/Allura/allura/tests/test_globals.py
index 6e3a702..335f71d 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -912,6 +912,9 @@ class TestHandlePaging(unittest.TestCase):
         c.user.set_pref('results_per_page', 'bar')
         self.assertEqual(g.handle_paging(None, 0, 30), (30, 0, 0))
 
+    def test_with_invalid_page(self):
+        self.assertEqual(g.handle_paging(10, 'asdf', 30), (10, 0, 0))
+
 
 class TestIconRender(object):
 


[allura] 32/41: [#8349] python-modernize -n -w --no-diffs -f types .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 2163e969fd6f21d672d239f69d613112dd6a4620
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 15:26:33 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f types .
---
 Allura/allura/lib/AsciiDammit.py | 2 +-
 Allura/allura/lib/utils.py       | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Allura/allura/lib/AsciiDammit.py b/Allura/allura/lib/AsciiDammit.py
index db0604c..131f3a0 100644
--- a/Allura/allura/lib/AsciiDammit.py
+++ b/Allura/allura/lib/AsciiDammit.py
@@ -176,7 +176,7 @@ def _repl(match, html=0):
     "Replace the matched character with its HTML or ASCII equivalent."
     g = match.group(0)
     a = CHARS.get(g, g)
-    if isinstance(a, types.TupleType):
+    if isinstance(a, tuple):
         a = a[html]
         if html:
             a = '&' + a + ';'
diff --git a/Allura/allura/lib/utils.py b/Allura/allura/lib/utils.py
index 7cf1526..ab7247a 100644
--- a/Allura/allura/lib/utils.py
+++ b/Allura/allura/lib/utils.py
@@ -790,7 +790,7 @@ def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
 
     This function was borrowed from Django
     """
-    if strings_only and isinstance(s, (types.NoneType, int)):
+    if strings_only and isinstance(s, (type(None), int)):
         return s
     elif not isinstance(s, six.string_types):
         try:


[allura] 20/41: [#8349] python-modernize -n -w --no-diffs -f xrange_six .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 107b818e38b4773784e0a2568f3a68aa4e7afc3d
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 14:37:18 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f xrange_six .
---
 Allura/allura/command/taskd_cleanup.py                         | 1 +
 Allura/allura/controllers/site_admin.py                        | 1 +
 Allura/allura/lib/custom_middleware.py                         | 1 +
 Allura/allura/lib/helpers.py                                   | 3 ++-
 Allura/allura/lib/multifactor.py                               | 5 +++--
 Allura/allura/lib/plugin.py                                    | 3 ++-
 Allura/allura/lib/utils.py                                     | 3 ++-
 Allura/allura/lib/widgets/form_fields.py                       | 3 ++-
 Allura/allura/model/discuss.py                                 | 1 +
 Allura/allura/model/repository.py                              | 1 +
 Allura/allura/model/stats.py                                   | 1 +
 Allura/allura/scripts/create_sitemap_files.py                  | 1 +
 Allura/allura/tests/functional/test_auth.py                    | 3 ++-
 Allura/allura/tests/functional/test_discuss.py                 | 1 +
 Allura/allura/tests/functional/test_home.py                    | 1 +
 Allura/allura/tests/model/test_discussion.py                   | 1 +
 Allura/allura/tests/test_commands.py                           | 5 +++--
 Allura/allura/tests/test_tasks.py                              | 1 +
 Allura/allura/tests/test_utils.py                              | 3 ++-
 Allura/allura/tests/test_webhooks.py                           | 1 +
 Allura/allura/tests/unit/test_post_model.py                    | 3 ++-
 Allura/allura/tests/unit/test_session.py                       | 5 +++--
 Allura/allura/websetup/bootstrap.py                            | 1 +
 ForgeBlog/forgeblog/tests/functional/test_root.py              | 1 +
 ForgeDiscussion/forgediscussion/tests/functional/test_forum.py | 1 +
 ForgeImporters/forgeimporters/github/tests/test_wiki.py        | 1 +
 ForgeSVN/forgesvn/model/svn.py                                 | 3 ++-
 ForgeSVN/forgesvn/tests/model/test_repository.py               | 1 +
 ForgeTracker/forgetracker/search.py                            | 3 ++-
 ForgeTracker/forgetracker/tests/functional/test_root.py        | 1 +
 ForgeWiki/forgewiki/tests/functional/test_root.py              | 1 +
 ForgeWiki/forgewiki/tests/test_models.py                       | 1 +
 scripts/perf/benchmark-scm.py                                  | 1 +
 scripts/perf/call_count.py                                     | 3 ++-
 scripts/perf/generate-projects.py                              | 1 +
 scripts/perf/load-up-forum.py                                  | 1 +
 scripts/perf/sstress.py                                        | 5 +++--
 scripts/project-import.py                                      | 1 +
 38 files changed, 56 insertions(+), 18 deletions(-)

diff --git a/Allura/allura/command/taskd_cleanup.py b/Allura/allura/command/taskd_cleanup.py
index 4c50737..5523410 100644
--- a/Allura/allura/command/taskd_cleanup.py
+++ b/Allura/allura/command/taskd_cleanup.py
@@ -26,6 +26,7 @@ from ming.orm.ormsession import ThreadLocalORMSession
 
 from allura import model as M
 from . import base
+from six.moves import range
 
 
 class TaskdCleanupCommand(base.Command):
diff --git a/Allura/allura/controllers/site_admin.py b/Allura/allura/controllers/site_admin.py
index f703a11..fb50b2a 100644
--- a/Allura/allura/controllers/site_admin.py
+++ b/Allura/allura/controllers/site_admin.py
@@ -52,6 +52,7 @@ import allura
 from six.moves.urllib.parse import urlparse
 from webhelpers import paginate
 import six
+from six.moves import range
 
 
 log = logging.getLogger(__name__)
diff --git a/Allura/allura/lib/custom_middleware.py b/Allura/allura/lib/custom_middleware.py
index 4771599..061d792 100644
--- a/Allura/allura/lib/custom_middleware.py
+++ b/Allura/allura/lib/custom_middleware.py
@@ -34,6 +34,7 @@ import six
 
 from allura.lib import helpers as h
 import allura.model.repository
+from six.moves import range
 
 log = logging.getLogger(__name__)
 
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index bfa5038..c861136 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -43,6 +43,7 @@ import cgi
 import emoji
 import tg
 import six
+from six.moves import range
 try:
     import cchardet as chardet
 except ImportError:
@@ -717,7 +718,7 @@ def _add_table_line_numbers_to_text(txt):
 
     def _len_to_str_column(l, start=1):
         max_num = l + start
-        return '\n'.join(map(_prepend_whitespaces, range(start, max_num), [max_num] * l))
+        return '\n'.join(map(_prepend_whitespaces, list(range(start, max_num)), [max_num] * l))
 
     lines = txt.splitlines(True)
     linenumbers = '<td class="linenos"><div class="linenodiv"><pre>' + \
diff --git a/Allura/allura/lib/multifactor.py b/Allura/allura/lib/multifactor.py
index c120a16..8e34d24 100644
--- a/Allura/allura/lib/multifactor.py
+++ b/Allura/allura/lib/multifactor.py
@@ -43,6 +43,7 @@ from allura.model.multifactor import RecoveryCode
 from allura.lib.utils import umask
 import six
 from io import open
+from six.moves import range
 
 
 log = logging.getLogger(__name__)
@@ -361,7 +362,7 @@ class RecoveryCodeService(object):
     def generate_one_code(self):
         # for compatibility with Google PAM file, we only do digits
         length = asint(config.get('auth.multifactor.recovery_code.length', 8))
-        return ''.join([random.choice(string.digits) for i in xrange(length)])
+        return ''.join([random.choice(string.digits) for i in range(length)])
 
     def regenerate_codes(self, user):
         '''
@@ -372,7 +373,7 @@ class RecoveryCodeService(object):
         '''
         count = asint(config.get('auth.multifactor.recovery_code.count', 10))
         codes = [
-            self.generate_one_code() for i in xrange(count)
+            self.generate_one_code() for i in range(count)
         ]
         self.replace_codes(user, codes)
         return codes
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index 6e0d9d6..32b6dae 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -36,6 +36,7 @@ from base64 import b64encode
 from datetime import datetime, timedelta
 import calendar
 import six
+from six.moves import range
 
 try:
     import ldap
@@ -575,7 +576,7 @@ class LocalAuthenticationProvider(AuthenticationProvider):
         from allura import model as M
         if salt is None:
             salt = ''.join(chr(randint(1, 0x7f))
-                           for i in xrange(M.User.SALT_LEN))
+                           for i in range(M.User.SALT_LEN))
         hashpass = sha256(salt + password.encode('utf-8')).digest()
         return 'sha256' + salt + b64encode(hashpass)
 
diff --git a/Allura/allura/lib/utils.py b/Allura/allura/lib/utils.py
index 336383a..5485966 100644
--- a/Allura/allura/lib/utils.py
+++ b/Allura/allura/lib/utils.py
@@ -60,6 +60,7 @@ from ming.utils import LazyProperty
 from ming.odm.odmsession import ODMCursor
 from ming.odm import session
 import six
+from six.moves import range
 
 MARKDOWN_EXTENSIONS = ['.markdown', '.mdown', '.mkdn', '.mkd', '.md']
 
@@ -183,7 +184,7 @@ def lsub_utf8(s, n):
 def chunked_list(l, n):
     """ Yield successive n-sized chunks from l.
     """
-    for i in xrange(0, len(l), n):
+    for i in range(0, len(l), n):
         yield l[i:i + n]
 
 
diff --git a/Allura/allura/lib/widgets/form_fields.py b/Allura/allura/lib/widgets/form_fields.py
index 64beee5..7610325 100644
--- a/Allura/allura/lib/widgets/form_fields.py
+++ b/Allura/allura/lib/widgets/form_fields.py
@@ -28,6 +28,7 @@ from webhelpers import paginate
 import ew as ew_core
 import ew.jinja2_ew as ew
 import six
+from six.moves import range
 
 log = logging.getLogger(__name__)
 
@@ -310,7 +311,7 @@ class PageList(ew_core.Widget):
             params = request.GET.copy()
             params['page'] = page - page_offset
             return url(request.path, params)
-        return paginate.Page(range(count), page + page_offset, int(limit),
+        return paginate.Page(list(range(count)), page + page_offset, int(limit),
                              url=page_url)
 
     def prepare_context(self, context):
diff --git a/Allura/allura/model/discuss.py b/Allura/allura/model/discuss.py
index 708f974..3f70757 100644
--- a/Allura/allura/model/discuss.py
+++ b/Allura/allura/model/discuss.py
@@ -43,6 +43,7 @@ from .attachments import BaseAttachment
 from .auth import User, ProjectRole, AlluraUserProperty
 from .timeline import ActivityObject
 from .types import MarkdownCache
+from six.moves import range
 
 log = logging.getLogger(__name__)
 
diff --git a/Allura/allura/model/repository.py b/Allura/allura/model/repository.py
index 7d34967..f55f024 100644
--- a/Allura/allura/model/repository.py
+++ b/Allura/allura/model/repository.py
@@ -61,6 +61,7 @@ from .project import AppConfig
 from .session import main_doc_session
 from .session import repository_orm_session
 from io import open
+from six.moves import range
 
 
 log = logging.getLogger(__name__)
diff --git a/Allura/allura/model/stats.py b/Allura/allura/model/stats.py
index c5f07b8..baa24ec 100644
--- a/Allura/allura/model/stats.py
+++ b/Allura/allura/model/stats.py
@@ -29,6 +29,7 @@ from datetime import timedelta
 import difflib
 
 from allura.model.session import main_orm_session
+from six.moves import range
 
 
 class Stats(MappedClass):
diff --git a/Allura/allura/scripts/create_sitemap_files.py b/Allura/allura/scripts/create_sitemap_files.py
index e2347bb..1eaeb07 100644
--- a/Allura/allura/scripts/create_sitemap_files.py
+++ b/Allura/allura/scripts/create_sitemap_files.py
@@ -46,6 +46,7 @@ from allura import model as M
 from allura.lib import security, utils
 from allura.scripts import ScriptTask
 from io import open
+from six.moves import range
 
 
 MAX_SITEMAP_URLS = 50000
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index 67479e1..710c675 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -55,6 +55,7 @@ from allura.lib import plugin
 from allura.lib import helpers as h
 from allura.lib.multifactor import TotpService, RecoveryCodeService
 import six
+from six.moves import range
 
 
 def unentity(s):
@@ -2597,7 +2598,7 @@ class TestTwoFactor(TestController):
         r = r.follow()
 
         # try some invalid codes
-        for i in xrange(3):
+        for i in range(3):
             r.form['code'] = 'invalid-code'
             r = r.form.submit()
             assert_in('Invalid code', r)
diff --git a/Allura/allura/tests/functional/test_discuss.py b/Allura/allura/tests/functional/test_discuss.py
index 4f633d8..aa12d4c 100644
--- a/Allura/allura/tests/functional/test_discuss.py
+++ b/Allura/allura/tests/functional/test_discuss.py
@@ -28,6 +28,7 @@ from allura import model as M
 from allura.lib import helpers as h
 from tg import config
 from io import open
+from six.moves import range
 
 
 
diff --git a/Allura/allura/tests/functional/test_home.py b/Allura/allura/tests/functional/test_home.py
index 686b31e..71b3c7e 100644
--- a/Allura/allura/tests/functional/test_home.py
+++ b/Allura/allura/tests/functional/test_home.py
@@ -29,6 +29,7 @@ import allura
 from allura.tests import TestController
 from allura.tests import decorators as td
 from allura import model as M
+from six.moves import range
 
 
 class TestProjectHome(TestController):
diff --git a/Allura/allura/tests/model/test_discussion.py b/Allura/allura/tests/model/test_discussion.py
index 91ca97d..b4e5f22 100644
--- a/Allura/allura/tests/model/test_discussion.py
+++ b/Allura/allura/tests/model/test_discussion.py
@@ -40,6 +40,7 @@ from allura import model as M
 from allura.lib import helpers as h
 from allura.tests import TestController
 from alluratest.controller import setup_global_objects
+from six.moves import range
 
 
 def setUp():
diff --git a/Allura/allura/tests/test_commands.py b/Allura/allura/tests/test_commands.py
index 344ca39..e069359 100644
--- a/Allura/allura/tests/test_commands.py
+++ b/Allura/allura/tests/test_commands.py
@@ -34,6 +34,7 @@ from allura.command import base, script, set_neighborhood_features, \
 from allura import model as M
 from allura.lib.exceptions import InvalidNBFeatureValueError
 from allura.tests import decorators as td
+from six.moves import range
 
 test_config = pkg_resources.resource_filename(
     'allura', '../test.ini') + '#main'
@@ -503,7 +504,7 @@ class TestReindexCommand(object):
         add_artifacts.post.side_effect = on_post
         cmd = show_models.ReindexCommand('reindex')
         cmd.options, args = cmd.parser.parse_args([])
-        cmd._post_add_artifacts(range(5))
+        cmd._post_add_artifacts(list(range(5)))
         kw = {'update_solr': cmd.options.solr, 'update_refs': cmd.options.refs}
         expected = [
             call([0, 1, 2, 3, 4], **kw),
@@ -526,7 +527,7 @@ class TestReindexCommand(object):
         cmd = show_models.ReindexCommand('reindex')
         cmd.options = Mock(ming_config=None)
         with td.raises(pymongo.errors.InvalidDocument):
-            cmd._post_add_artifacts(range(5))
+            cmd._post_add_artifacts(list(range(5)))
 
     @td.with_wiki  # so there's some artifacts to reindex
     def test_ming_config(self):
diff --git a/Allura/allura/tests/test_tasks.py b/Allura/allura/tests/test_tasks.py
index 85e21ca..79e873c 100644
--- a/Allura/allura/tests/test_tasks.py
+++ b/Allura/allura/tests/test_tasks.py
@@ -53,6 +53,7 @@ from allura.tasks import export_tasks
 from allura.tasks import admin_tasks
 from allura.tests import decorators as td
 from allura.lib.decorators import event_handler, task
+from six.moves import range
 
 
 class TestRepoTasks(unittest.TestCase):
diff --git a/Allura/allura/tests/test_utils.py b/Allura/allura/tests/test_utils.py
index 675886c..d3cff56 100644
--- a/Allura/allura/tests/test_utils.py
+++ b/Allura/allura/tests/test_utils.py
@@ -46,6 +46,7 @@ from alluratest.controller import setup_unit_test
 from allura import model as M
 from allura.lib import utils
 from allura.lib import helpers as h
+from six.moves import range
 
 
 @patch.dict('allura.lib.utils.tg.config', clear=True, foo='bar', baz='true')
@@ -99,7 +100,7 @@ class TestChunkedIterator(unittest.TestCase):
 class TestChunkedList(unittest.TestCase):
 
     def test_chunked_list(self):
-        l = range(10)
+        l = list(range(10))
         chunks = list(utils.chunked_list(l, 3))
         self.assertEqual(len(chunks), 4)
         self.assertEqual(len(chunks[0]), 3)
diff --git a/Allura/allura/tests/test_webhooks.py b/Allura/allura/tests/test_webhooks.py
index a7e1b8f..6430ae6 100644
--- a/Allura/allura/tests/test_webhooks.py
+++ b/Allura/allura/tests/test_webhooks.py
@@ -51,6 +51,7 @@ from alluratest.controller import (
     TestRestApiBase,
 )
 import six
+from six.moves import range
 
 
 # important to be distinct from 'test' and 'test2' which ForgeGit and
diff --git a/Allura/allura/tests/unit/test_post_model.py b/Allura/allura/tests/unit/test_post_model.py
index 838989e..475c3c6 100644
--- a/Allura/allura/tests/unit/test_post_model.py
+++ b/Allura/allura/tests/unit/test_post_model.py
@@ -24,6 +24,7 @@ from allura import model as M
 from allura.tests.unit import WithDatabase
 from allura.tests.unit import patches
 from allura.tests.unit.factories import create_post
+from six.moves import range
 
 
 class TestPostModel(WithDatabase):
@@ -46,7 +47,7 @@ class TestPostModel(WithDatabase):
         self.post.text = """\
 This is a **bold thing**, 40 chars here.
 * Here's the first item in our list.
-* And here's the second item.""" + ','.join(map(str, range(200)))
+* And here's the second item.""" + ','.join(map(str, list(range(200))))
         assert 'allura_id' in self.post.activity_extras
         summary = self.post.activity_extras['summary']
         assert summary.startswith("This is a bold thing, 40 chars here. Here's the first item in our list. "
diff --git a/Allura/allura/tests/unit/test_session.py b/Allura/allura/tests/unit/test_session.py
index 3be5484..65168ed 100644
--- a/Allura/allura/tests/unit/test_session.py
+++ b/Allura/allura/tests/unit/test_session.py
@@ -30,6 +30,7 @@ from allura.model.session import (
     ArtifactSessionExtension,
     substitute_extensions,
 )
+from six.moves import range
 
 
 def test_extensions_cm():
@@ -232,7 +233,7 @@ class TestBatchIndexer(TestCase):
                 e.args = e.args + ("doc:  {'task_name': 'allura.tasks.index_tasks.add_artifacts', ........",)
                 raise e
         index_tasks.add_artifacts.post.side_effect = on_post
-        self.ext._post(index_tasks.add_artifacts, range(5))
+        self.ext._post(index_tasks.add_artifacts, list(range(5)))
         expected = [
             mock.call([0, 1, 2, 3, 4]),
             mock.call([0, 1]),
@@ -253,4 +254,4 @@ class TestBatchIndexer(TestCase):
             raise pymongo.errors.InvalidDocument("Cannot encode object...")
         index_tasks.add_artifacts.post.side_effect = on_post
         with td.raises(pymongo.errors.InvalidDocument):
-            self.ext._post(index_tasks.add_artifacts, range(5))
+            self.ext._post(index_tasks.add_artifacts, list(range(5)))
diff --git a/Allura/allura/websetup/bootstrap.py b/Allura/allura/websetup/bootstrap.py
index 7ddc24f..93a966c 100644
--- a/Allura/allura/websetup/bootstrap.py
+++ b/Allura/allura/websetup/bootstrap.py
@@ -45,6 +45,7 @@ from allura.websetup.schema import REGISTRY
 
 from forgewiki import model as WM
 import six
+from six.moves import range
 
 log = logging.getLogger(__name__)
 
diff --git a/ForgeBlog/forgeblog/tests/functional/test_root.py b/ForgeBlog/forgeblog/tests/functional/test_root.py
index 4358a98..d7e551b 100644
--- a/ForgeBlog/forgeblog/tests/functional/test_root.py
+++ b/ForgeBlog/forgeblog/tests/functional/test_root.py
@@ -28,6 +28,7 @@ from mock import patch
 
 from allura.lib import helpers as h
 from alluratest.controller import TestController
+from six.moves import range
 
 
 class Test(TestController):
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
index a7d80e8..865ed4d 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
@@ -45,6 +45,7 @@ from allura.tests import decorators as td
 
 from forgediscussion import model as FM
 from io import open
+from six.moves import range
 
 log = logging.getLogger(__name__)
 
diff --git a/ForgeImporters/forgeimporters/github/tests/test_wiki.py b/ForgeImporters/forgeimporters/github/tests/test_wiki.py
index cdbcb19..910ac91 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_wiki.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_wiki.py
@@ -33,6 +33,7 @@ from alluratest.controller import setup_basic_test
 from forgeimporters.github.wiki import GitHubWikiImporter
 from forgeimporters.github.utils import GitHubMarkdownConverter
 from forgeimporters.github import GitHubOAuthMixin
+from six.moves import range
 
 
 # important to be distinct from 'test' which ForgeWiki uses, so that the
diff --git a/ForgeSVN/forgesvn/model/svn.py b/ForgeSVN/forgesvn/model/svn.py
index c91c1f9..13c54ad 100644
--- a/ForgeSVN/forgesvn/model/svn.py
+++ b/ForgeSVN/forgesvn/model/svn.py
@@ -48,6 +48,7 @@ from allura.model.auth import User
 from allura.model.repository import zipdir
 from allura.model import repository as RM
 from io import open
+from six.moves import range
 
 log = logging.getLogger(__name__)
 
@@ -327,7 +328,7 @@ class SVNImplementation(M.RepositoryImplementation):
         commit) and ending with the root (first commit).
         """
         head_revno = self.head
-        return map(self._oid, range(head_revno, 0, -1))
+        return map(self._oid, list(range(head_revno, 0, -1)))
 
     def new_commits(self, all_commits=False):
         head_revno = self.head
diff --git a/ForgeSVN/forgesvn/tests/model/test_repository.py b/ForgeSVN/forgesvn/tests/model/test_repository.py
index 046c17a..07b14a5 100644
--- a/ForgeSVN/forgesvn/tests/model/test_repository.py
+++ b/ForgeSVN/forgesvn/tests/model/test_repository.py
@@ -52,6 +52,7 @@ from forgesvn.tests import with_svn
 from allura.tests.decorators import with_tool
 import six
 from io import open
+from six.moves import range
 
 
 class TestNewRepo(unittest.TestCase):
diff --git a/ForgeTracker/forgetracker/search.py b/ForgeTracker/forgetracker/search.py
index ca15e85..1f0aa2c 100644
--- a/ForgeTracker/forgetracker/search.py
+++ b/ForgeTracker/forgetracker/search.py
@@ -20,6 +20,7 @@ from tg import tmpl_context as c
 
 from allura.lib.search import search
 import six
+from six.moves import range
 
 
 FACET_PARAMS = {
@@ -61,6 +62,6 @@ def get_facets(solr_hit):
     if solr_hit is not None:
         for facet_name, values in six.iteritems(solr_hit.facets['facet_fields']):
             field_name = facet_name.rsplit('_s', 1)[0]
-            values = [(values[i], values[i+1]) for i in xrange(0, len(values), 2)]
+            values = [(values[i], values[i+1]) for i in range(0, len(values), 2)]
             result[field_name] = values
     return result
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index fe74abc..294b01e 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -59,6 +59,7 @@ from allura.tests import decorators as td
 from allura.tasks import mail_tasks
 from ming.orm.ormsession import ThreadLocalORMSession
 import six
+from six.moves import range
 
 
 class TrackerTestController(TestController):
diff --git a/ForgeWiki/forgewiki/tests/functional/test_root.py b/ForgeWiki/forgewiki/tests/functional/test_root.py
index 49f30da..f917c1e 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_root.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_root.py
@@ -37,6 +37,7 @@ from allura.tests import decorators as td
 from alluratest.controller import TestController
 
 from forgewiki import model
+from six.moves import range
 
 
 class TestRootController(TestController):
diff --git a/ForgeWiki/forgewiki/tests/test_models.py b/ForgeWiki/forgewiki/tests/test_models.py
index 199ec63..44fe2e0 100644
--- a/ForgeWiki/forgewiki/tests/test_models.py
+++ b/ForgeWiki/forgewiki/tests/test_models.py
@@ -28,6 +28,7 @@ from allura.lib import helpers as h
 
 
 from forgewiki.model import Page
+from six.moves import range
 
 
 class TestPageSnapshots(TestController):
diff --git a/scripts/perf/benchmark-scm.py b/scripts/perf/benchmark-scm.py
index 341beb9..1e23cb9 100755
--- a/scripts/perf/benchmark-scm.py
+++ b/scripts/perf/benchmark-scm.py
@@ -30,6 +30,7 @@ import git
 import pysvn
 from mercurial import ui, hg, cmdutil
 import six
+from six.moves import range
 
 
 def main(opts):
diff --git a/scripts/perf/call_count.py b/scripts/perf/call_count.py
index baf7d95..830f493 100755
--- a/scripts/perf/call_count.py
+++ b/scripts/perf/call_count.py
@@ -39,6 +39,7 @@ from allura.tests.decorators import patch_middleware_config
 
 from forgewiki import model as WM
 from io import open
+from six.moves import range
 
 
 def parse_args():
@@ -123,7 +124,7 @@ def count_page(test, url, verbose=False, debug_html=False):
         print(url, resp.status)
         if debug_html:
             debug_filename = 'call-{}.html'.format(''.join([random.choice(string.ascii_letters + string.digits)
-                                                   for n in xrange(10)]))
+                                                   for n in range(10)]))
             with open(debug_filename, 'w') as out:
                 out.write(resp.body)
             print(debug_filename)
diff --git a/scripts/perf/generate-projects.py b/scripts/perf/generate-projects.py
index 1591170..d03e68f 100644
--- a/scripts/perf/generate-projects.py
+++ b/scripts/perf/generate-projects.py
@@ -21,6 +21,7 @@ from __future__ import absolute_import
 import re
 from ming.odm import ThreadLocalORMSession
 from allura import model as M
+from six.moves import range
 
 def main(start, cnt):
     n = M.Neighborhood.query.get(url_prefix='/p/')
diff --git a/scripts/perf/load-up-forum.py b/scripts/perf/load-up-forum.py
index cce16d9..92e6710 100644
--- a/scripts/perf/load-up-forum.py
+++ b/scripts/perf/load-up-forum.py
@@ -27,6 +27,7 @@ from forgediscussion.model import ForumPost, Forum
 from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter, ArgumentTypeError
 from allura.lib import helpers as h
 from random import randint
+from six.moves import range
 
 
 log = logging.getLogger(__name__)
diff --git a/scripts/perf/sstress.py b/scripts/perf/sstress.py
index 04c0a22..546025e 100644
--- a/scripts/perf/sstress.py
+++ b/scripts/perf/sstress.py
@@ -27,6 +27,7 @@ from __future__ import absolute_import
 import smtplib
 import threading
 import time
+from six.moves import range
 
 C = 5
 N = 1000
@@ -38,7 +39,7 @@ EMAIL_TEXT = 'X' * SIZE
 
 
 def main():
-    threads = [threading.Thread(target=stress) for x in xrange(C)]
+    threads = [threading.Thread(target=stress) for x in range(C)]
     begin = time.time()
     for t in threads:
         t.start()
@@ -52,7 +53,7 @@ def main():
 
 def stress():
     server = smtplib.SMTP(SERVER, PORT)
-    for x in xrange(N / C):
+    for x in range(N / C):
         server.sendmail('sstress@localhost', TOADDR, EMAIL_TEXT)
 
 if __name__ == '__main__':
diff --git a/scripts/project-import.py b/scripts/project-import.py
index 584a02f..6c153fc 100644
--- a/scripts/project-import.py
+++ b/scripts/project-import.py
@@ -35,6 +35,7 @@ from allura.lib import helpers as h
 from allura.lib.plugin import ProjectRegistrationProvider
 import six
 from io import open
+from six.moves import range
 
 log = logging.getLogger(__name__)
 


[allura] 15/41: [#8349] various adjustments for open() changes

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 5e9dbf45b3273ff88c4de2175585a7c0cba26e29
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 14:07:28 2020 -0500

    [#8349] various adjustments for open() changes
---
 Allura/allura/command/script.py                  | 2 +-
 Allura/allura/model/repository.py                | 2 +-
 Allura/allura/tests/functional/test_discuss.py   | 4 ++--
 Allura/allura/tests/model/test_filesystem.py     | 2 +-
 Allura/allura/tests/test_globals.py              | 6 +++---
 Allura/allura/tests/test_helpers.py              | 2 +-
 ForgeImporters/forgeimporters/tests/test_base.py | 2 +-
 scripts/project-import.py                        | 2 +-
 scripts/teamforge-import.py                      | 6 +++---
 9 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/Allura/allura/command/script.py b/Allura/allura/command/script.py
index 42f0136..ee15316 100644
--- a/Allura/allura/command/script.py
+++ b/Allura/allura/command/script.py
@@ -67,7 +67,7 @@ class ScriptCommand(base.Command):
                     cProfile.run(fp, '%s.profile' %
                                  os.path.basename(self.args[1]))
                 else:
-                    exec fp in ns
+                    exec fp.read() in ns
 
 
 class SetToolAccessCommand(base.Command):
diff --git a/Allura/allura/model/repository.py b/Allura/allura/model/repository.py
index 160be35..2460919 100644
--- a/Allura/allura/model/repository.py
+++ b/Allura/allura/model/repository.py
@@ -229,7 +229,7 @@ class RepositoryImplementation(object):
             self._repo.fs_path, self._repo.name, tg.config.get(
                 'scm.magic_file', '.ALLURA-REPOSITORY'))
         with open(magic_file, 'w') as f:
-            f.write(self._repo.repo_id)
+            f.write(six.ensure_text(self._repo.repo_id))
         os.chmod(magic_file, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
         self._setup_hooks(source_path)
 
diff --git a/Allura/allura/tests/functional/test_discuss.py b/Allura/allura/tests/functional/test_discuss.py
index 97d0a90..4f633d8 100644
--- a/Allura/allura/tests/functional/test_discuss.py
+++ b/Allura/allura/tests/functional/test_discuss.py
@@ -481,7 +481,7 @@ class TestAttachment(TestDiscussBase):
 
     def test_deleted_post_attachment(self):
         f = os.path.join(os.path.dirname(__file__), '..', 'data', 'user.png')
-        with open(f) as f:
+        with open(f, 'rb') as f:
             pic = f.read()
         self.app.post(
             self.post_link + 'attach',
@@ -503,7 +503,7 @@ class TestAttachment(TestDiscussBase):
         moderator = {'username': str('test-admin')}
         # set up attachment
         f = os.path.join(os.path.dirname(__file__), '..', 'data', 'user.png')
-        with open(f) as f:
+        with open(f, 'rb') as f:
             pic = f.read()
         self.app.post(
             self.post_link + 'attach',
diff --git a/Allura/allura/tests/model/test_filesystem.py b/Allura/allura/tests/model/test_filesystem.py
index 8d4eff9..104267a 100644
--- a/Allura/allura/tests/model/test_filesystem.py
+++ b/Allura/allura/tests/model/test_filesystem.py
@@ -155,7 +155,7 @@ class TestFile(TestCase):
     def test_image(self):
         path = os.path.join(
             os.path.dirname(__file__), '..', 'data', 'user.png')
-        with open(path) as fp:
+        with open(path, 'rb') as fp:
             f, t = File.save_image(
                 'user.png',
                 fp,
diff --git a/Allura/allura/tests/test_globals.py b/Allura/allura/tests/test_globals.py
index 2c278db..9393da8 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -90,7 +90,7 @@ def test_macro_projects():
     p_nbhd = M.Neighborhood.query.get(name='Projects')
     p_test = M.Project.query.get(shortname='test', neighborhood_id=p_nbhd._id)
     c.project = p_test
-    icon_file = open(file_path)
+    icon_file = open(file_path, 'rb')
     M.ProjectFile.save_image(
         file_name, icon_file, content_type='image/png',
         square=True, thumbnail_size=(48, 48),
@@ -99,7 +99,7 @@ def test_macro_projects():
     p_test2 = M.Project.query.get(
         shortname='test2', neighborhood_id=p_nbhd._id)
     c.project = p_test2
-    icon_file = open(file_path)
+    icon_file = open(file_path, 'rb')
     M.ProjectFile.save_image(
         file_name, icon_file, content_type='image/png',
         square=True, thumbnail_size=(48, 48),
@@ -108,7 +108,7 @@ def test_macro_projects():
     p_sub1 = M.Project.query.get(
         shortname='test/sub1', neighborhood_id=p_nbhd._id)
     c.project = p_sub1
-    icon_file = open(file_path)
+    icon_file = open(file_path, 'rb')
     M.ProjectFile.save_image(
         file_name, icon_file, content_type='image/png',
         square=True, thumbnail_size=(48, 48),
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index b49be5f..97e7dac 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -587,7 +587,7 @@ def test_convert_bools():
 
 def test_base64uri_img():
     img_file = path.join(path.dirname(__file__), 'data', 'user.png')
-    with open(img_file) as img_file_handle:
+    with open(img_file, 'rb') as img_file_handle:
         img = PIL.Image.open(img_file_handle)
         b64img = h.base64uri(img)
         assert b64img.startswith('data:image/png;base64,'), b64img[:100]
diff --git a/ForgeImporters/forgeimporters/tests/test_base.py b/ForgeImporters/forgeimporters/tests/test_base.py
index ffbaa40..8049ea5 100644
--- a/ForgeImporters/forgeimporters/tests/test_base.py
+++ b/ForgeImporters/forgeimporters/tests/test_base.py
@@ -367,7 +367,7 @@ def test_save_importer_upload(giup, os):
     os.makedirs.side_effect = OSError(errno.EEXIST, 'foo')
     _open = mock.MagicMock()
     fp = _open.return_value.__enter__.return_value
-    with mock.patch('__builtin__.open', _open):
+    with mock.patch.object(base, 'open', _open):
         base.save_importer_upload('project', 'file', 'data')
     os.makedirs.assert_called_once_with('path')
     _open.assert_called_once_with('path/file', 'w')
diff --git a/scripts/project-import.py b/scripts/project-import.py
index a83ed48..06df746 100644
--- a/scripts/project-import.py
+++ b/scripts/project-import.py
@@ -285,7 +285,7 @@ def create_project(p, nbhd, options):
                      granted_by_neighborhood_id=nbhd._id)
 
     if p.icon:
-        with open(p.icon) as icon_file:
+        with open(p.icon, 'rb') as icon_file:
             project.save_icon(p.icon, icon_file)
 
     project.notifications_disabled = False
diff --git a/scripts/teamforge-import.py b/scripts/teamforge-import.py
index 5789179..6c3cad1 100644
--- a/scripts/teamforge-import.py
+++ b/scripts/teamforge-import.py
@@ -370,7 +370,7 @@ def create_project(pid, nbhd):
         icon_file = 'emsignia-SOLUTIONS-blue.gif'
     if project.icon:
         M.ProjectFile.remove(dict(project_id=project._id, category='icon'))
-    with open(os.path.join('..', 'scripts', icon_file)) as fp:
+    with open(os.path.join('..', 'scripts', icon_file), 'rb') as fp:
         M.ProjectFile.save_image(
             icon_file, fp, content_type=utils.guess_mime_type(icon_file),
             square=True, thumbnail_size=(48, 48),
@@ -666,9 +666,9 @@ def check_unsupported_tools(project):
 
 def load(project_id, *paths):
     in_file = os.path.join(options.output_dir, project_id, *paths)
-    with open(in_file) as input:
+    with open(in_file, encoding='utf-8') as input:
         content = input.read()
-    return six.text_type(content, 'utf-8')
+    return content
 
 
 def loadjson(*args):


[allura] 02/41: misc: avoid filter=foo erroring

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit f543c2bc49bdce24f51592d445d4b052ebb50e91
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 11:43:01 2020 -0500

    misc: avoid filter=foo erroring
---
 Allura/allura/lib/validators.py                         | 7 ++++++-
 Allura/allura/tests/test_validators.py                  | 2 ++
 ForgeTracker/forgetracker/model/ticket.py               | 3 ++-
 ForgeTracker/forgetracker/tests/functional/test_root.py | 3 +++
 ForgeTracker/forgetracker/tracker_main.py               | 6 +-----
 5 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/Allura/allura/lib/validators.py b/Allura/allura/lib/validators.py
index 7bcbbb4..2041dcb 100644
--- a/Allura/allura/lib/validators.py
+++ b/Allura/allura/lib/validators.py
@@ -257,13 +257,18 @@ class JsonValidator(fev.FancyValidator):
 
 class JsonConverter(fev.FancyValidator):
 
-    """Deserializes a string to JSON and returns a Python object"""
+    """
+    Deserializes a string to JSON and returns a Python object
+    Must be an object, not a simple literal
+    """
 
     def _to_python(self, value, state):
         try:
             obj = json.loads(value)
         except ValueError, e:
             raise fe.Invalid('Invalid JSON: ' + str(e), value, state)
+        if not isinstance(obj, dict):
+            raise fe.Invalid('Not a dict (JSON object)', value, state)
         return obj
 
 
diff --git a/Allura/allura/tests/test_validators.py b/Allura/allura/tests/test_validators.py
index 3f9d27a..4d75135 100644
--- a/Allura/allura/tests/test_validators.py
+++ b/Allura/allura/tests/test_validators.py
@@ -45,6 +45,8 @@ class TestJsonConverter(unittest.TestCase):
     def test_invalid(self):
         with self.assertRaises(fe.Invalid):
             self.val.to_python('{')
+        with self.assertRaises(fe.Invalid):
+            self.val.to_python('3')
 
 
 class TestJsonFile(unittest.TestCase):
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index 6824e42..e33ec35 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -1261,7 +1261,8 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
         limit, page, start = g.handle_paging(limit, page, default=25)
         count = 0
         tickets = []
-        if filter is None: filter = {}
+        if filter is None:
+            filter = {}
         refined_sort = sort if sort else 'ticket_num_i desc'
         if 'ticket_num_i' not in refined_sort:
             refined_sort += ',ticket_num_i asc'
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index 8c50d0d..0428654 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -1381,6 +1381,9 @@ class TestFunctionalController(TrackerTestController):
         assert '3 results' in response, response.showbrowser()
         assert 'test third ticket' in response, response.showbrowser()
 
+        # 'filter' is special kwarg, don't let it cause problems
+        r = self.app.get('/p/test/bugs/search/?q=test&filter=blah')
+
     def test_search_with_strange_chars(self):
         r = self.app.get('/p/test/bugs/search/?' +
                          urlencode({'q': 'tést'}))
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index 50c5db8..ddd836b 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -92,7 +92,7 @@ search_validators = dict(
     limit=validators.Int(if_invalid=None),
     page=validators.Int(if_empty=0, if_invalid=0),
     sort=validators.UnicodeString(if_empty=None),
-    filter=V.JsonConverter(if_empty={}),
+    filter=V.JsonConverter(if_empty={}, if_invalid={}),
     deleted=validators.StringBool(if_empty=False))
 
 
@@ -714,10 +714,6 @@ class RootController(BaseController, FeedController):
         elif deleted and not has_access(c.app, 'delete'):
             deleted = False
 
-        if not isinstance(filter, dict):
-            # JsonConverter above can return an int, string, etc, if users give bad inputs, but it needs to be a dict
-            filter = {}
-
         # it's just our original query mangled and sent back to us
         kw.pop('q', None)
         result = TM.Ticket.paged_query_or_search(c.app.config, c.user,


[allura] 16/41: [#8349] remove leading 0 numbers that are not really octal

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 390dbf2c56294a697794a8628ee328a75de66c4e
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 14:10:46 2020 -0500

    [#8349] remove leading 0 numbers that are not really octal
---
 Allura/allura/tests/test_helpers.py                 | 2 +-
 Allura/allura/tests/test_plugin.py                  | 2 +-
 Allura/allura/tests/test_utils.py                   | 2 +-
 Allura/allura/tests/test_webhooks.py                | 2 +-
 Allura/allura/tests/unit/test_ldap_auth_provider.py | 2 +-
 ForgeUserStats/forgeuserstats/tests/test_model.py   | 8 ++++----
 6 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index 97e7dac..ecb265c 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -319,7 +319,7 @@ def test_inject_user(context):
 
 def test_datetimeformat():
     from datetime import date
-    assert h.datetimeformat(date(2013, 01, 01)) == '2013-01-01 00:00:00'
+    assert h.datetimeformat(date(2013, 1, 1)) == '2013-01-01 00:00:00'
 
 
 def test_nl2br_jinja_filter():
diff --git a/Allura/allura/tests/test_plugin.py b/Allura/allura/tests/test_plugin.py
index 83c865f..8e02010 100644
--- a/Allura/allura/tests/test_plugin.py
+++ b/Allura/allura/tests/test_plugin.py
@@ -632,7 +632,7 @@ class TestLocalAuthenticationProvider(object):
 
     def test_get_last_password_updated(self):
         user = Mock()
-        user.last_password_updated = dt.datetime(2014, 06, 04, 13, 13, 13)
+        user.last_password_updated = dt.datetime(2014, 6, 4, 13, 13, 13)
         upd = self.provider.get_last_password_updated(user)
         assert_equal(upd, user.last_password_updated)
 
diff --git a/Allura/allura/tests/test_utils.py b/Allura/allura/tests/test_utils.py
index c34e7c0..675886c 100644
--- a/Allura/allura/tests/test_utils.py
+++ b/Allura/allura/tests/test_utils.py
@@ -345,7 +345,7 @@ def test_empty_cursor():
 
 def test_DateJSONEncoder():
     data = {'message': 'Hi!',
-            'date': dt.datetime(2015, 01, 30, 13, 13, 13)}
+            'date': dt.datetime(2015, 1, 30, 13, 13, 13)}
     result = json.dumps(data, cls=utils.DateJSONEncoder)
     assert_equal(result, '{"date": "2015-01-30T13:13:13Z", "message": "Hi!"}')
 
diff --git a/Allura/allura/tests/test_webhooks.py b/Allura/allura/tests/test_webhooks.py
index adba095..a7e1b8f 100644
--- a/Allura/allura/tests/test_webhooks.py
+++ b/Allura/allura/tests/test_webhooks.py
@@ -652,7 +652,7 @@ class TestModels(TestWebhookBase):
 
     @patch('allura.model.webhook.dt', autospec=True)
     def test_update_limit(self, dt_mock):
-        _now = dt.datetime(2015, 02, 02, 13, 39)
+        _now = dt.datetime(2015, 2, 2, 13, 39)
         dt_mock.datetime.utcnow.return_value = _now
         assert_equal(self.wh.last_sent, None)
         self.wh.update_limit()
diff --git a/Allura/allura/tests/unit/test_ldap_auth_provider.py b/Allura/allura/tests/unit/test_ldap_auth_provider.py
index 5945581..1896e5e 100644
--- a/Allura/allura/tests/unit/test_ldap_auth_provider.py
+++ b/Allura/allura/tests/unit/test_ldap_auth_provider.py
@@ -155,6 +155,6 @@ class TestLdapAuthenticationProvider(object):
 
     def test_get_last_password_updated(self):
         user = Mock()
-        user.last_password_updated = datetime(2014, 06, 04, 13, 13, 13)
+        user.last_password_updated = datetime(2014, 6, 4, 13, 13, 13)
         upd = self.provider.get_last_password_updated(user)
         assert_equal(upd, user.last_password_updated)
diff --git a/ForgeUserStats/forgeuserstats/tests/test_model.py b/ForgeUserStats/forgeuserstats/tests/test_model.py
index afa94a1..308728e 100644
--- a/ForgeUserStats/forgeuserstats/tests/test_model.py
+++ b/ForgeUserStats/forgeuserstats/tests/test_model.py
@@ -443,12 +443,12 @@ class TestUserStats(unittest.TestCase):
                    login_datetime) < timedelta(seconds=1)
 
     def test_start_date(self):
-        stats = USM.UserStats(registration_date=datetime(2012, 04, 01))
-        self.assertEqual(stats.start_date, datetime(2012, 04, 01))
+        stats = USM.UserStats(registration_date=datetime(2012, 4, 1))
+        self.assertEqual(stats.start_date, datetime(2012, 4, 1))
         with h.push_config(config, **{'userstats.start_date': '2013-04-01'}):
-            self.assertEqual(stats.start_date, datetime(2013, 04, 01))
+            self.assertEqual(stats.start_date, datetime(2013, 4, 1))
         with h.push_config(config, **{'userstats.start_date': '2011-04-01'}):
-            self.assertEqual(stats.start_date, datetime(2012, 04, 01))
+            self.assertEqual(stats.start_date, datetime(2012, 4, 1))
 
     @mock.patch('allura.model.stats.difflib.unified_diff')
     def test_count_loc(self, unified_diff):


[allura] 10/41: [#8349] further updates after urllib import changes

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 6276654e81c9094983a73b26fc7531b0b59d856b
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 13:24:56 2020 -0500

    [#8349] further updates after urllib import changes
---
 Allura/allura/lib/custom_middleware.py           |  8 ++++++--
 Allura/allura/lib/helpers.py                     |  1 -
 Allura/allura/tests/test_helpers.py              | 16 ++++++++--------
 ForgeImporters/forgeimporters/tests/test_base.py |  2 +-
 4 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/Allura/allura/lib/custom_middleware.py b/Allura/allura/lib/custom_middleware.py
index b1fd554..4771599 100644
--- a/Allura/allura/lib/custom_middleware.py
+++ b/Allura/allura/lib/custom_middleware.py
@@ -30,6 +30,7 @@ from tg.support.middlewares import _call_wsgi_application as call_wsgi_applicati
 from timermiddleware import Timer, TimerMiddleware
 from webob import exc, Request
 import pysolr
+import six
 
 from allura.lib import helpers as h
 import allura.model.repository
@@ -295,7 +296,10 @@ class AlluraTimerMiddleware(TimerMiddleware):
         import ming
         import pymongo
         import socket
-        import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
+        if six.PY2:
+            import urllib2 as urlopen_pkg
+        else:
+            import urllib.requests as urlopen_pkg
         import activitystream
         import pygments
         import difflib
@@ -341,7 +345,7 @@ class AlluraTimerMiddleware(TimerMiddleware):
             Timer('socket_write', socket._fileobject, 'write', 'writelines',
                   'flush', debug_each_call=False),
             Timer('solr', pysolr.Solr, 'add', 'delete', 'search', 'commit'),
-            Timer('urlopen', urllib2, 'urlopen'),
+            Timer('urlopen', urlopen_pkg, 'urlopen'),
             Timer('base_repo_tool.{method_name}',
                   allura.model.repository.RepositoryImplementation, 'last_commit_ids'),
             Timer('pygments', pygments, 'highlight'),  # often called from within a template so will overlap w/ jinja
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index d874a0d..3812707 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -24,7 +24,6 @@ import os
 import os.path
 import difflib
 import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
-import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
 import re
 import unicodedata
 import json
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index 0308f17..514f43e 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -438,13 +438,13 @@ back\\\\\-slash escaped
 
 class TestUrlOpen(TestCase):
 
-    @patch('allura.lib.helpers.urllib2')
-    def test_no_error(self, urllib2):
+    @patch('six.moves.urllib.request.urlopen')
+    def test_no_error(self, urlopen):
         r = h.urlopen('myurl')
-        self.assertEqual(r, six.moves.urllib.request.urlopen.return_value)
-        six.moves.urllib.request.urlopen.assert_called_once_with('myurl', timeout=None)
+        self.assertEqual(r, urlopen.return_value)
+        urlopen.assert_called_once_with('myurl', timeout=None)
 
-    @patch('allura.lib.helpers.urllib2.urlopen')
+    @patch('six.moves.urllib.request.urlopen')
     def test_socket_timeout(self, urlopen):
         import socket
 
@@ -454,7 +454,7 @@ class TestUrlOpen(TestCase):
         self.assertRaises(socket.timeout, h.urlopen, 'myurl')
         self.assertEqual(urlopen.call_count, 4)
 
-    @patch('allura.lib.helpers.urllib2.urlopen')
+    @patch('six.moves.urllib.request.urlopen')
     def test_socket_reset(self, urlopen):
         import socket
         import errno
@@ -465,7 +465,7 @@ class TestUrlOpen(TestCase):
         self.assertRaises(socket.error, h.urlopen, 'myurl')
         self.assertEqual(urlopen.call_count, 4)
 
-    @patch('allura.lib.helpers.urllib2.urlopen')
+    @patch('six.moves.urllib.request.urlopen')
     def test_handled_http_error(self, urlopen):
         from six.moves.urllib.error import HTTPError
 
@@ -475,7 +475,7 @@ class TestUrlOpen(TestCase):
         self.assertRaises(HTTPError, h.urlopen, 'myurl')
         self.assertEqual(urlopen.call_count, 4)
 
-    @patch('allura.lib.helpers.urllib2.urlopen')
+    @patch('six.moves.urllib.request.urlopen')
     def test_unhandled_http_error(self, urlopen):
         from six.moves.urllib.error import HTTPError
 
diff --git a/ForgeImporters/forgeimporters/tests/test_base.py b/ForgeImporters/forgeimporters/tests/test_base.py
index 917bea5..ffbaa40 100644
--- a/ForgeImporters/forgeimporters/tests/test_base.py
+++ b/ForgeImporters/forgeimporters/tests/test_base.py
@@ -36,7 +36,7 @@ from forgeimporters import base
 class TestProjectExtractor(TestCase):
 
     @mock.patch('forgeimporters.base.h.urlopen')
-    @mock.patch('forgeimporters.base.urllib2.Request')
+    @mock.patch('six.moves.urllib.request.Request')
     def test_urlopen(self, Request, urlopen):
         r = base.ProjectExtractor.urlopen('myurl', data='foo')
         Request.assert_called_once_with('myurl', data='foo')


[allura] 29/41: [#8349] python-modernize -n -w --no-diffs -f input_six .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit e0d292f81e64822c7d9145aefbd980dccab5f66e
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 15:21:19 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f input_six .
---
 Allura/allura/websetup/bootstrap.py | 3 ++-
 Allura/ldap-setup.py                | 3 ++-
 scripts/new_ticket.py               | 5 +++--
 scripts/wiki-copy.py                | 5 +++--
 4 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/Allura/allura/websetup/bootstrap.py b/Allura/allura/websetup/bootstrap.py
index 93a966c..46c8832 100644
--- a/Allura/allura/websetup/bootstrap.py
+++ b/Allura/allura/websetup/bootstrap.py
@@ -46,6 +46,7 @@ from allura.websetup.schema import REGISTRY
 from forgewiki import model as WM
 import six
 from six.moves import range
+from six.moves import input
 
 log = logging.getLogger(__name__)
 
@@ -99,7 +100,7 @@ def bootstrap(command, conf, vars):
         root = create_user('Root', make_project=False)
     else:
         from getpass import getpass
-        root_name = raw_input('Enter username for root user (default "root"): ').strip()
+        root_name = input('Enter username for root user (default "root"): ').strip()
         if not root_name:
             root_name = 'root'
         ok = False
diff --git a/Allura/ldap-setup.py b/Allura/ldap-setup.py
index 600c547..11ccc97 100644
--- a/Allura/ldap-setup.py
+++ b/Allura/ldap-setup.py
@@ -27,6 +27,7 @@ from contextlib import contextmanager
 from tempfile import mkstemp
 from six.moves.configparser import ConfigParser, NoOptionError
 from io import open
+from six.moves import input
 
 logging.basicConfig(level=logging.DEBUG)
 log = logging.getLogger('ldap-setup')
@@ -88,7 +89,7 @@ def get_value(key, default):
         default = config.get('scm', key)
     except NoOptionError:
         pass
-    value = raw_input('%s? [%s]' % (key, default))
+    value = input('%s? [%s]' % (key, default))
     if not value:
         value = default
     config.set('scm', key, value)
diff --git a/scripts/new_ticket.py b/scripts/new_ticket.py
index 47dd921..0c16169 100755
--- a/scripts/new_ticket.py
+++ b/scripts/new_ticket.py
@@ -23,6 +23,7 @@ import sys
 import argparse
 import requests
 from pprint import pprint
+from six.moves import input
 
 
 def get_parser():
@@ -43,8 +44,8 @@ def get_opts():
 
 if __name__ == '__main__':
     opts = get_opts()
-    access_token = raw_input('Access (bearer) token: ')
-    summary = raw_input('Summary: ')
+    access_token = input('Access (bearer) token: ')
+    summary = input('Summary: ')
     print('Description (C-d to end):')
     print('-----------------------------------------------')
     description = sys.stdin.read()
diff --git a/scripts/wiki-copy.py b/scripts/wiki-copy.py
index 383f0e7..7769357 100644
--- a/scripts/wiki-copy.py
+++ b/scripts/wiki-copy.py
@@ -31,6 +31,7 @@ from six.moves.configparser import ConfigParser, NoOptionError
 import webbrowser
 import oauth2 as oauth
 from io import open
+from six.moves import input
 
 
 def main():
@@ -103,7 +104,7 @@ def make_oauth_client(base_url):
             print(("Go to %s" % pin_url))
         else:
             webbrowser.open(pin_url)
-        oauth_verifier = raw_input('What is the PIN? ')
+        oauth_verifier = input('What is the PIN? ')
 
         token = oauth.Token(
             request_token['oauth_token'], request_token['oauth_token_secret'])
@@ -133,7 +134,7 @@ def option(cp, section, key, prompt=None):
     if cp.has_option(section, key):
         value = cp.get(section, key)
     else:
-        value = raw_input(prompt or ('%s: ' % key))
+        value = input(prompt or ('%s: ' % key))
         cp.set(section, key, value)
     return value
 


[allura] 01/41: Misc: check apache config file as part of docker build

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit c39f8c24b865fc5d106a8e2bf2063266debe917c
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 11:00:24 2020 -0500

    Misc: check apache config file as part of docker build
---
 scm_config/git-http/Dockerfile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/scm_config/git-http/Dockerfile b/scm_config/git-http/Dockerfile
index 9673421..b2adbc2 100644
--- a/scm_config/git-http/Dockerfile
+++ b/scm_config/git-http/Dockerfile
@@ -46,6 +46,7 @@ RUN a2enmod cgi proxy proxy_http
 ADD ./git-http.conf /etc/apache2/sites-available/
 RUN a2dissite 000-default.conf
 RUN a2ensite git-http.conf
+RUN apachectl configtest
 
 ADD git-http-backend-wrapper.sh /usr/lib/git-core
 RUN adduser www-data sudo


[allura] 23/41: [#8349] python-modernize -n -w --no-diffs -f map .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit f57671b87874d1ba94c66ca600f85106c9dff09a
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 14:42:20 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f map .
---
 Allura/allura/app.py                                      | 11 ++++++-----
 Allura/allura/controllers/site_admin.py                   |  3 ++-
 Allura/allura/ext/admin/admin_main.py                     |  3 ++-
 Allura/allura/ext/search/search_main.py                   |  1 +
 Allura/allura/lib/exceptions.py                           |  1 +
 Allura/allura/lib/helpers.py                              |  3 ++-
 Allura/allura/lib/mail_util.py                            |  5 +++--
 Allura/allura/lib/multifactor.py                          |  3 ++-
 Allura/allura/lib/utils.py                                |  5 +++--
 Allura/allura/model/discuss.py                            |  3 ++-
 Allura/allura/model/project.py                            |  3 ++-
 Allura/allura/tests/functional/test_neighborhood.py       |  3 ++-
 Allura/allura/tests/functional/test_personal_dashboard.py |  3 ++-
 Allura/allura/tests/functional/test_user_profile.py       |  3 ++-
 Allura/allura/tests/unit/test_post_model.py               |  1 +
 Allura/allura/tests/unit/test_session.py                  |  3 ++-
 Allura/allura/version.py                                  |  1 +
 Allura/allura/webhooks.py                                 |  3 ++-
 ForgeBlog/forgeblog/version.py                            |  1 +
 ForgeChat/forgechat/version.py                            |  1 +
 ForgeDiscussion/forgediscussion/version.py                |  1 +
 ForgeFeedback/forgefeedback/version.py                    |  1 +
 ForgeGit/forgegit/version.py                              |  1 +
 ForgeImporters/forgeimporters/github/wiki.py              |  8 ++++----
 ForgeLink/forgelink/version.py                            |  1 +
 ForgeSVN/forgesvn/model/svn.py                            |  3 ++-
 ForgeSVN/forgesvn/svn_main.py                             |  3 ++-
 ForgeSVN/forgesvn/version.py                              |  1 +
 ForgeTracker/forgetracker/tracker_main.py                 |  3 ++-
 ForgeTracker/forgetracker/version.py                      |  1 +
 ForgeUserStats/forgeuserstats/version.py                  |  1 +
 ForgeWiki/forgewiki/version.py                            |  1 +
 scripts/perf/parse_timings.py                             |  1 +
 scripts/teamforge-import.py                               |  9 +++++----
 34 files changed, 64 insertions(+), 31 deletions(-)

diff --git a/Allura/allura/app.py b/Allura/allura/app.py
index 0d2d2a2..17e4943 100644
--- a/Allura/allura/app.py
+++ b/Allura/allura/app.py
@@ -51,6 +51,7 @@ from allura import model as M
 from allura.tasks import index_tasks
 import six
 from io import open
+from six.moves import map
 
 log = logging.getLogger(__name__)
 
@@ -859,7 +860,7 @@ class DefaultAdminController(BaseController, AdminControllerMixin):
     @require_post()
     def unblock_user(self, user_id=None, perm=None, **kw):
         try:
-            user_id = map(ObjectId, user_id)
+            user_id = list(map(ObjectId, user_id))
         except InvalidId:
             user_id = []
         users = model.User.query.find({'_id': {'$in': user_id}}).all()
@@ -1006,9 +1007,9 @@ class DefaultAdminController(BaseController, AdminControllerMixin):
 
             def get_role(_id):
                 return model.ProjectRole.query.get(_id=ObjectId(_id))
-            groups = map(get_role, group_ids)
-            new_groups = map(get_role, new_group_ids)
-            del_groups = map(get_role, del_group_ids)
+            groups = list(map(get_role, group_ids))
+            new_groups = list(map(get_role, new_group_ids))
+            del_groups = list(map(get_role, del_group_ids))
 
             def group_names(groups):
                 return ', '.join((role.name or '<Unnamed>') for role in groups if role)
@@ -1020,7 +1021,7 @@ class DefaultAdminController(BaseController, AdminControllerMixin):
                     group_names(groups + new_groups),
                     self.app.config.options['mount_point']))
 
-            role_ids = map(ObjectId, group_ids + new_group_ids)
+            role_ids = list(map(ObjectId, group_ids + new_group_ids))
             self.app.config.acl += [
                 model.ACE.allow(r, perm) for r in role_ids]
 
diff --git a/Allura/allura/controllers/site_admin.py b/Allura/allura/controllers/site_admin.py
index fb50b2a..14b5ffd 100644
--- a/Allura/allura/controllers/site_admin.py
+++ b/Allura/allura/controllers/site_admin.py
@@ -53,6 +53,7 @@ from six.moves.urllib.parse import urlparse
 from webhelpers import paginate
 import six
 from six.moves import range
+from six.moves import map
 
 
 log = logging.getLogger(__name__)
@@ -300,7 +301,7 @@ class SiteAdminController(object):
         return {
             'q': q,
             'f': f,
-            'objects': map(convert_fields, objects),
+            'objects': list(map(convert_fields, objects)),
             'count': count,
             'page': page,
             'limit': limit,
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index bda9878..883c2ec 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -54,6 +54,7 @@ from allura.lib.widgets.project_list import ProjectScreenshots
 
 from . import widgets as aw
 import six
+from six.moves import map
 
 
 log = logging.getLogger(__name__)
@@ -1002,7 +1003,7 @@ class PermissionsController(BaseController):
                         '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)
+            role_ids = list(map(ObjectId, group_ids + new_group_ids))
             permissions[perm] = role_ids
         c.project.acl = []
         for perm, role_ids in six.iteritems(permissions):
diff --git a/Allura/allura/ext/search/search_main.py b/Allura/allura/ext/search/search_main.py
index 98abc4a..6218c34 100644
--- a/Allura/allura/ext/search/search_main.py
+++ b/Allura/allura/ext/search/search_main.py
@@ -30,6 +30,7 @@ from allura import version
 from allura.lib.search import search_app
 from allura.lib.widgets.search import SearchResults, SearchHelp
 from allura.controllers import BaseController
+from six.moves import map
 
 log = logging.getLogger(__name__)
 
diff --git a/Allura/allura/lib/exceptions.py b/Allura/allura/lib/exceptions.py
index ed7ef0b..43d3643 100644
--- a/Allura/allura/lib/exceptions.py
+++ b/Allura/allura/lib/exceptions.py
@@ -19,6 +19,7 @@ from __future__ import unicode_literals
 from __future__ import absolute_import
 import webob.exc
 from formencode import Invalid
+from six.moves import map
 
 
 class ForgeError(Exception):
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index c861136..1efbc39 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -44,6 +44,7 @@ import emoji
 import tg
 import six
 from six.moves import range
+from six.moves import map
 try:
     import cchardet as chardet
 except ImportError:
@@ -934,7 +935,7 @@ def split_select_field_options(field_options):
         # it's better to pass properly encoded byte-string
         field_options = shlex.split(field_options.encode('utf-8'))
         # convert splitted string back to unicode
-        field_options = map(really_unicode, field_options)
+        field_options = list(map(really_unicode, field_options))
     except ValueError:
         field_options = field_options.split()
         # After regular split field_options might contain a " characters,
diff --git a/Allura/allura/lib/mail_util.py b/Allura/allura/lib/mail_util.py
index 7a425c5..b00019e 100644
--- a/Allura/allura/lib/mail_util.py
+++ b/Allura/allura/lib/mail_util.py
@@ -35,6 +35,7 @@ from tg import app_globals as g
 from allura.lib.utils import ConfigProxy
 from allura.lib import exceptions as exc
 from allura.lib import helpers as h
+from six.moves import map
 
 log = logging.getLogger(__name__)
 
@@ -283,11 +284,11 @@ class SMTPClient(object):
             references = ['<%s>' % r for r in aslist(references)]
             message['References'] = Header(*references)
         content = message.as_string()
-        smtp_addrs = map(_parse_smtp_addr, addrs)
+        smtp_addrs = list(map(_parse_smtp_addr, addrs))
         smtp_addrs = [a for a in smtp_addrs if isvalid(a)]
         if not smtp_addrs:
             log.warning('No valid addrs in %s, so not sending mail',
-                        map(six.text_type, addrs))
+                        list(map(six.text_type, addrs)))
             return
         try:
             self._client.sendmail(
diff --git a/Allura/allura/lib/multifactor.py b/Allura/allura/lib/multifactor.py
index 8e34d24..e39ac28 100644
--- a/Allura/allura/lib/multifactor.py
+++ b/Allura/allura/lib/multifactor.py
@@ -44,6 +44,7 @@ from allura.lib.utils import umask
 import six
 from io import open
 from six.moves import range
+from six.moves import map
 
 
 log = logging.getLogger(__name__)
@@ -300,7 +301,7 @@ class GoogleAuthenticatorPamFilesystemMixin(object):
         rate_limits = gaf.options['RATE_LIMIT'].split(' ')
         num_allowed = int(rate_limits.pop(0))
         time_allowed = int(rate_limits.pop(0))
-        prev_attempts = map(int, rate_limits)
+        prev_attempts = list(map(int, rate_limits))
 
         ok, attempts_in_limit = check_rate_limit(num_allowed, time_allowed, prev_attempts)
 
diff --git a/Allura/allura/lib/utils.py b/Allura/allura/lib/utils.py
index 49151ef..5439482 100644
--- a/Allura/allura/lib/utils.py
+++ b/Allura/allura/lib/utils.py
@@ -62,6 +62,7 @@ from ming.odm import session
 import six
 from six.moves import range
 from six.moves import zip
+from six.moves import map
 
 MARKDOWN_EXTENSIONS = ['.markdown', '.mdown', '.mkdn', '.mkd', '.md']
 
@@ -219,7 +220,7 @@ class AntiSpam(object):
             self.spinner_text = request.params['spinner']
             self.timestamp = int(self.timestamp_text)
             self.spinner = self._unwrap(self.spinner_text)
-        self.spinner_ord = map(ord, self.spinner)
+        self.spinner_ord = list(map(ord, self.spinner))
         self.random_padding = [random.randint(0, 255) for x in self.spinner]
         self.honey_class = self.enc(self.spinner_text, css_safe=True)
 
@@ -269,7 +270,7 @@ class AntiSpam(object):
         plain.encode('ascii')
 
         plain = ([len(plain)]
-                 + map(ord, plain)
+                 + list(map(ord, plain))
                  + self.random_padding[:len(self.spinner_ord) - len(plain) - 1])
         enc = ''.join(six.unichr(p ^ s) for p, s in zip(plain, self.spinner_ord))
         enc = six.ensure_binary(enc)
diff --git a/Allura/allura/model/discuss.py b/Allura/allura/model/discuss.py
index 3f70757..41d2c6d 100644
--- a/Allura/allura/model/discuss.py
+++ b/Allura/allura/model/discuss.py
@@ -44,6 +44,7 @@ from .auth import User, ProjectRole, AlluraUserProperty
 from .timeline import ActivityObject
 from .types import MarkdownCache
 from six.moves import range
+from six.moves import map
 
 log = logging.getLogger(__name__)
 
@@ -624,7 +625,7 @@ class Post(Message, VersionedArtifact, ActivityObject, ReactableArtifact):
 
     def add_multiple_attachments(self, file_info):
         if isinstance(file_info, list):
-            map(self.add_attachment, file_info)
+            list(map(self.add_attachment, file_info))
         else:
             self.add_attachment(file_info)
 
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index 23fc27b..5c95d19 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -63,6 +63,7 @@ from .monq_model import MonQTask
 
 from .filesystem import File
 import six
+from six.moves import map
 
 log = logging.getLogger(__name__)
 
@@ -381,7 +382,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
 
     @memoize
     def icon_sized(self, w):
-        allowed_sizes = map(int, aslist(config.get('project_icon_sizes', '16 24 32 48 64 72 96')))
+        allowed_sizes = list(map(int, aslist(config.get('project_icon_sizes', '16 24 32 48 64 72 96'))))
         if w not in allowed_sizes:
             raise ValueError('Width must be one of {} (see project_icon_sizes in your .ini file)'.format(allowed_sizes))
         if w == DEFAULT_ICON_WIDTH:
diff --git a/Allura/allura/tests/functional/test_neighborhood.py b/Allura/allura/tests/functional/test_neighborhood.py
index fd4e29b..ce23cbe 100644
--- a/Allura/allura/tests/functional/test_neighborhood.py
+++ b/Allura/allura/tests/functional/test_neighborhood.py
@@ -38,6 +38,7 @@ from allura.tests import decorators as td
 from allura.lib import helpers as h
 from allura.lib import utils
 from alluratest.controller import setup_trove_categories
+from six.moves import map
 
 
 class TestNeighborhood(TestController):
@@ -598,7 +599,7 @@ class TestNeighborhood(TestController):
             antispam=True,
             extra_environ=dict(username=str('root')))
         cookies = r.headers.getall('Set-Cookie')
-        flash_msg_cookies = map(six.moves.urllib.parse.unquote, cookies)
+        flash_msg_cookies = list(map(six.moves.urllib.parse.unquote, cookies))
 
         assert any('Internal Error' in cookie for cookie in flash_msg_cookies)
 
diff --git a/Allura/allura/tests/functional/test_personal_dashboard.py b/Allura/allura/tests/functional/test_personal_dashboard.py
index 15a1821..b625ba7 100644
--- a/Allura/allura/tests/functional/test_personal_dashboard.py
+++ b/Allura/allura/tests/functional/test_personal_dashboard.py
@@ -32,6 +32,7 @@ from allura.tests import TestController
 from allura.tests import decorators as td
 from alluratest.controller import setup_global_objects, setup_unit_test
 from forgetracker.tests.functional.test_root import TrackerTestController
+from six.moves import map
 
 
 class TestPersonalDashboard(TestController):
@@ -51,7 +52,7 @@ class TestPersonalDashboard(TestController):
             m.name = n
             m.load()().display.return_value = 'Section %s' % n
             return m
-        eps = map(ep, ['a', 'b', 'c', 'd'])
+        eps = list(map(ep, ['a', 'b', 'c', 'd']))
         order = {'personal_dashboard_sections.order': 'b, d,c , f '}
         with mock.patch('allura.lib.helpers.iter_entry_points') as iep:
             with mock.patch.dict(tg.config, order):
diff --git a/Allura/allura/tests/functional/test_user_profile.py b/Allura/allura/tests/functional/test_user_profile.py
index 71e3848..a6e3ec1 100644
--- a/Allura/allura/tests/functional/test_user_profile.py
+++ b/Allura/allura/tests/functional/test_user_profile.py
@@ -25,6 +25,7 @@ from alluratest.controller import TestRestApiBase
 from allura.model import Project, User
 from allura.tests import decorators as td
 from allura.tests import TestController
+from six.moves import map
 
 
 class TestUserProfile(TestController):
@@ -211,7 +212,7 @@ class TestUserProfile(TestController):
             m.name = n
             m.load()().display.return_value = 'Section %s' % n
             return m
-        eps = map(ep, ['a', 'b', 'c', 'd'])
+        eps = list(map(ep, ['a', 'b', 'c', 'd']))
         order = {'user_profile_sections.order': 'b, d,c , f '}
         if hasattr(type(app), '_sections'):
             delattr(type(app), '_sections')
diff --git a/Allura/allura/tests/unit/test_post_model.py b/Allura/allura/tests/unit/test_post_model.py
index 475c3c6..e99e673 100644
--- a/Allura/allura/tests/unit/test_post_model.py
+++ b/Allura/allura/tests/unit/test_post_model.py
@@ -25,6 +25,7 @@ from allura.tests.unit import WithDatabase
 from allura.tests.unit import patches
 from allura.tests.unit.factories import create_post
 from six.moves import range
+from six.moves import map
 
 
 class TestPostModel(WithDatabase):
diff --git a/Allura/allura/tests/unit/test_session.py b/Allura/allura/tests/unit/test_session.py
index 65168ed..601c6b4 100644
--- a/Allura/allura/tests/unit/test_session.py
+++ b/Allura/allura/tests/unit/test_session.py
@@ -31,6 +31,7 @@ from allura.model.session import (
     substitute_extensions,
 )
 from six.moves import range
+from six.moves import map
 
 
 def test_extensions_cm():
@@ -105,7 +106,7 @@ class TestIndexerSessionExtension(TestSessionExtension):
         self.extension.objects_deleted = deleted
         self.extension.after_flush()
         self.tasks['add'].post.assert_called_once_with([1, 2, 3, 4, 5])
-        self.tasks['del'].post.assert_called_once_with(map(id, deleted))
+        self.tasks['del'].post.assert_called_once_with(list(map(id, deleted)))
 
     def test_flush_skips_update(self):
         modified = [self._mock_indexable(_id=i) for i in range(5)]
diff --git a/Allura/allura/version.py b/Allura/allura/version.py
index 10bcc51..753d37a 100644
--- a/Allura/allura/version.py
+++ b/Allura/allura/version.py
@@ -16,5 +16,6 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from six.moves import map
 __version_info__ = (0, 1)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/Allura/allura/webhooks.py b/Allura/allura/webhooks.py
index 31b6bef..dfa6247 100644
--- a/Allura/allura/webhooks.py
+++ b/Allura/allura/webhooks.py
@@ -44,6 +44,7 @@ from allura.lib.decorators import require_post, task
 from allura.lib.utils import DateJSONEncoder
 from allura import model as M
 import six
+from six.moves import map
 
 
 log = logging.getLogger(__name__)
@@ -341,7 +342,7 @@ class SendWebhookHelper(object):
     @property
     def retries(self):
         t = aslist(config.get('webhook.retry', [60, 120, 240]))
-        return map(int, t)
+        return list(map(int, t))
 
     def sign(self, json_payload):
         signature = hmac.new(
diff --git a/ForgeBlog/forgeblog/version.py b/ForgeBlog/forgeblog/version.py
index 192acec..7fde7da 100644
--- a/ForgeBlog/forgeblog/version.py
+++ b/ForgeBlog/forgeblog/version.py
@@ -16,5 +16,6 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeChat/forgechat/version.py b/ForgeChat/forgechat/version.py
index 192acec..7fde7da 100644
--- a/ForgeChat/forgechat/version.py
+++ b/ForgeChat/forgechat/version.py
@@ -16,5 +16,6 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeDiscussion/forgediscussion/version.py b/ForgeDiscussion/forgediscussion/version.py
index 192acec..7fde7da 100644
--- a/ForgeDiscussion/forgediscussion/version.py
+++ b/ForgeDiscussion/forgediscussion/version.py
@@ -16,5 +16,6 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeFeedback/forgefeedback/version.py b/ForgeFeedback/forgefeedback/version.py
index 13480d0..f1464b2 100755
--- a/ForgeFeedback/forgefeedback/version.py
+++ b/ForgeFeedback/forgefeedback/version.py
@@ -16,5 +16,6 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeGit/forgegit/version.py b/ForgeGit/forgegit/version.py
index 192acec..7fde7da 100644
--- a/ForgeGit/forgegit/version.py
+++ b/ForgeGit/forgegit/version.py
@@ -16,5 +16,6 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeImporters/forgeimporters/github/wiki.py b/ForgeImporters/forgeimporters/github/wiki.py
index 9a0839b..d96a3c1 100644
--- a/ForgeImporters/forgeimporters/github/wiki.py
+++ b/ForgeImporters/forgeimporters/github/wiki.py
@@ -65,6 +65,7 @@ from forgewiki.converters import mediawiki2markdown
 
 
 import logging
+from six.moves import map
 log = logging.getLogger(__name__)
 
 
@@ -195,7 +196,7 @@ class GitHubWikiImporter(ToolImporter):
 
     def _set_available_pages(self, commit):
         pages = [blob.name for blob in commit.tree.traverse()]
-        pages = map(os.path.splitext, pages)
+        pages = list(map(os.path.splitext, pages))
         pages = [self._convert_page_name(name) for name, ext in pages
                  if ext in self.supported_formats]
         self.available_pages = pages
@@ -374,7 +375,7 @@ class GitHubWikiImporter(ToolImporter):
         title = options = None
         if len(link) == 1:
             link = link[0]
-        elif any(map(lambda opt: link[1].startswith(opt), available_options)):
+        elif any([link[1].startswith(opt) for opt in available_options]):
             # second element is option -> first is the link
             link, options = link[0], link[1:]
         else:
@@ -403,8 +404,7 @@ class GitHubWikiImporter(ToolImporter):
         # E.g. if you have two pages: a.md and A.md both [[a]] and [[A]] will refer a.md.
         # We're emulating this behavior using list of all available pages
         try:
-            idx = map(lambda p: p.lower(),
-                      self.available_pages).index(page.lower())
+            idx = [p.lower() for p in self.available_pages].index(page.lower())
         except ValueError:
             idx = None
         if idx is not None:
diff --git a/ForgeLink/forgelink/version.py b/ForgeLink/forgelink/version.py
index 192acec..7fde7da 100644
--- a/ForgeLink/forgelink/version.py
+++ b/ForgeLink/forgelink/version.py
@@ -16,5 +16,6 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeSVN/forgesvn/model/svn.py b/ForgeSVN/forgesvn/model/svn.py
index 13c54ad..7370104 100644
--- a/ForgeSVN/forgesvn/model/svn.py
+++ b/ForgeSVN/forgesvn/model/svn.py
@@ -49,6 +49,7 @@ from allura.model.repository import zipdir
 from allura.model import repository as RM
 from io import open
 from six.moves import range
+from six.moves import map
 
 log = logging.getLogger(__name__)
 
@@ -328,7 +329,7 @@ class SVNImplementation(M.RepositoryImplementation):
         commit) and ending with the root (first commit).
         """
         head_revno = self.head
-        return map(self._oid, list(range(head_revno, 0, -1)))
+        return list(map(self._oid, list(range(head_revno, 0, -1))))
 
     def new_commits(self, all_commits=False):
         head_revno = self.head
diff --git a/ForgeSVN/forgesvn/svn_main.py b/ForgeSVN/forgesvn/svn_main.py
index 3b48259..5fafbf7 100644
--- a/ForgeSVN/forgesvn/svn_main.py
+++ b/ForgeSVN/forgesvn/svn_main.py
@@ -47,6 +47,7 @@ from . import version
 from . import widgets
 from .controllers import BranchBrowser
 from .model.svn import svn_path_exists
+from six.moves import map
 
 log = logging.getLogger(__name__)
 
@@ -206,7 +207,7 @@ class SVNCommitBrowserController(BaseController):
             data['commits'].append(str(commit['id']))
             data['built_tree'][commit['id']] = {
                 'column': 0,
-                'parents': map(str, commit['parents']),
+                'parents': list(map(str, commit['parents'])),
                 'short_id': '[r%s]' % commit['id'],
                 'message': commit['message'],
                 'oid': str(commit['id']),
diff --git a/ForgeSVN/forgesvn/version.py b/ForgeSVN/forgesvn/version.py
index 192acec..7fde7da 100644
--- a/ForgeSVN/forgesvn/version.py
+++ b/ForgeSVN/forgesvn/version.py
@@ -16,5 +16,6 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index 2873051..e433ec3 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -84,6 +84,7 @@ from forgetracker.widgets.bin_form import BinForm
 from forgetracker.widgets.ticket_search import TicketSearchResults, MassEdit, MassEditForm, MassMoveForm
 from forgetracker.widgets.admin_custom_fields import TrackerFieldAdmin, TrackerFieldDisplay
 import six
+from six.moves import map
 
 log = logging.getLogger(__name__)
 
@@ -1861,7 +1862,7 @@ class RootRestController(BaseController, AppRestControllerMixin):
 
         results = TM.Ticket.paged_search(
             c.app.config, c.user, q, limit, page, sort, show_deleted=False)
-        results['tickets'] = map(_convert_ticket, results['tickets'])
+        results['tickets'] = list(map(_convert_ticket, results['tickets']))
         return results
 
     @expose()
diff --git a/ForgeTracker/forgetracker/version.py b/ForgeTracker/forgetracker/version.py
index 192acec..7fde7da 100644
--- a/ForgeTracker/forgetracker/version.py
+++ b/ForgeTracker/forgetracker/version.py
@@ -16,5 +16,6 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeUserStats/forgeuserstats/version.py b/ForgeUserStats/forgeuserstats/version.py
index 192acec..7fde7da 100644
--- a/ForgeUserStats/forgeuserstats/version.py
+++ b/ForgeUserStats/forgeuserstats/version.py
@@ -16,5 +16,6 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeWiki/forgewiki/version.py b/ForgeWiki/forgewiki/version.py
index 192acec..7fde7da 100644
--- a/ForgeWiki/forgewiki/version.py
+++ b/ForgeWiki/forgewiki/version.py
@@ -16,5 +16,6 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/scripts/perf/parse_timings.py b/scripts/perf/parse_timings.py
index e85243c..8d32c59 100644
--- a/scripts/perf/parse_timings.py
+++ b/scripts/perf/parse_timings.py
@@ -24,6 +24,7 @@ import json
 from datetime import datetime
 import argparse
 import sys
+from six.moves import map
 
 
 parser = argparse.ArgumentParser(description='Parse TimerMiddleware json lines (e.g. stats.log), filter them, output tab-delimited')
diff --git a/scripts/teamforge-import.py b/scripts/teamforge-import.py
index 0aca4a5..25fa95f 100644
--- a/scripts/teamforge-import.py
+++ b/scripts/teamforge-import.py
@@ -46,6 +46,7 @@ from allura.lib import helpers as h
 from allura.lib import utils
 import six
 from io import open
+from six.moves import map
 
 log = logging.getLogger('teamforge-import')
 
@@ -212,10 +213,10 @@ def get_project(project):
     save(json.dumps(dict(
         data=dict(data),
         access_level=access_level,
-        admins=map(dict, admins),
-        members=map(dict, members),
-        groups=map(dict, groups),
-        categories=map(dict, categories),
+        admins=list(map(dict, admins)),
+        members=list(map(dict, members)),
+        groups=list(map(dict, groups)),
+        categories=list(map(dict, categories)),
     ), default=str),
         project, project.id + '.json')
 


[allura] 41/41: [#8349] get syntax tests running on py3

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 3b041f3beeb7c5675d6234d15a4cab1c9cdf599c
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 17:44:01 2020 -0500

    [#8349] get syntax tests running on py3
---
 AlluraTest/alluratest/test_syntax.py | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/AlluraTest/alluratest/test_syntax.py b/AlluraTest/alluratest/test_syntax.py
index db3621c..3545641 100644
--- a/AlluraTest/alluratest/test_syntax.py
+++ b/AlluraTest/alluratest/test_syntax.py
@@ -31,8 +31,8 @@ def run(cmd):
     proc = Popen(cmd, shell=True, cwd=toplevel_dir, stdout=PIPE, stderr=PIPE)
     # must capture & reprint stdount, so that nosetests can capture it
     (stdout, stderr) = proc.communicate()
-    sys.stdout.write(stdout)
-    sys.stderr.write(stderr)
+    sys.stdout.write(stdout.decode('utf-8'))
+    sys.stderr.write(stderr.decode('utf-8'))
     return proc.returncode
 
 
@@ -106,6 +106,8 @@ class TestLinters(object):
 def create_many_lint_methods():
     proc = Popen(find_py, shell=True, cwd=toplevel_dir, stdout=PIPE, stderr=PIPE)
     (find_stdout, stderr) = proc.communicate()
+    find_stdout = find_stdout.decode('utf-8')
+    stderr = stderr.decode('utf-8')
     sys.stderr.write(stderr)
     assert proc.returncode == 0, proc.returncode
     py_files = find_stdout.split('\n')


[allura] 33/41: [#8349] python-modernize -n -w --no-diffs -f execfile .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit db8d22e28eb3fae58478560c832f990104e5ee02
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 15:31:20 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f execfile .
---
 scripts/ApacheAccessHandler.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/ApacheAccessHandler.py b/scripts/ApacheAccessHandler.py
index 3b1b1bd..39c35b6 100644
--- a/scripts/ApacheAccessHandler.py
+++ b/scripts/ApacheAccessHandler.py
@@ -48,7 +48,7 @@ def load_requests_lib(req):
     virtualenv_path = req.get_options().get('ALLURA_VIRTUALENV', None)
     if virtualenv_path:
         activate_this = '%s/bin/activate_this.py' % virtualenv_path
-        execfile(activate_this, {'__file__': activate_this})
+        exec(compile(open(activate_this, "rb").read(), activate_this, 'exec'), {'__file__': activate_this})
     global requests
     import requests as requests_lib
     requests = requests_lib


[allura] 19/41: [#8349] python-modernize -n -w --no-diffs -f basestring .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 0d44182eda590fa82c6db99be9565dfe35658755
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 14:35:59 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f basestring .
---
 Allura/allura/app.py                                     | 4 ++--
 Allura/allura/ext/admin/admin_main.py                    | 4 ++--
 Allura/allura/lib/app_globals.py                         | 2 +-
 Allura/allura/lib/helpers.py                             | 4 ++--
 Allura/allura/lib/mail_util.py                           | 4 ++--
 Allura/allura/lib/plugin.py                              | 2 +-
 Allura/allura/lib/utils.py                               | 2 +-
 Allura/allura/lib/validators.py                          | 2 +-
 Allura/allura/lib/widgets/form_fields.py                 | 2 +-
 Allura/allura/model/repository.py                        | 2 +-
 Allura/allura/tasks/mail_tasks.py                        | 8 ++++----
 AlluraTest/alluratest/validation.py                      | 4 ++--
 ForgeDiscussion/forgediscussion/widgets/forum_widgets.py | 3 ++-
 ForgeSVN/forgesvn/tests/model/test_repository.py         | 2 +-
 ForgeTracker/forgetracker/widgets/ticket_form.py         | 3 ++-
 scripts/project-import.py                                | 2 +-
 scripts/teamforge-import.py                              | 2 +-
 scripts/trac_import.py                                   | 2 +-
 18 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/Allura/allura/app.py b/Allura/allura/app.py
index 99ddc4f..0d2d2a2 100644
--- a/Allura/allura/app.py
+++ b/Allura/allura/app.py
@@ -993,9 +993,9 @@ class DefaultAdminController(BaseController, AdminControllerMixin):
             new_group_ids = args.get('new', [])
             del_group_ids = []
             group_ids = args.get('value', [])
-            if isinstance(new_group_ids, basestring):
+            if isinstance(new_group_ids, six.string_types):
                 new_group_ids = [new_group_ids]
-            if isinstance(group_ids, basestring):
+            if isinstance(group_ids, six.string_types):
                 group_ids = [group_ids]
 
             for acl in old_acl:
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index cd14c06..bda9878 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -985,9 +985,9 @@ class PermissionsController(BaseController):
             perm = args['id']
             new_group_ids = args.get('new', [])
             group_ids = args.get('value', [])
-            if isinstance(new_group_ids, basestring):
+            if isinstance(new_group_ids, six.string_types):
                 new_group_ids = [new_group_ids]
-            if isinstance(group_ids, basestring):
+            if isinstance(group_ids, six.string_types):
                 group_ids = [group_ids]
             # make sure the admin group has the admin permission
             if perm == 'admin':
diff --git a/Allura/allura/lib/app_globals.py b/Allura/allura/lib/app_globals.py
index 577c261..3809ad8 100644
--- a/Allura/allura/lib/app_globals.py
+++ b/Allura/allura/lib/app_globals.py
@@ -572,7 +572,7 @@ class Globals(object):
         'h.set_context() is preferred over this method'
         if isinstance(pid_or_project, M.Project):
             c.project = pid_or_project
-        elif isinstance(pid_or_project, basestring):
+        elif isinstance(pid_or_project, six.string_types):
             raise TypeError('need a Project instance, got %r' % pid_or_project)
         elif pid_or_project is None:
             c.project = None
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index 3f0b950..bfa5038 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -348,7 +348,7 @@ def set_context(project_shortname_or_id, mount_point=None, app_config_id=None, n
     if app_config_id is None:
         c.app = p.app_instance(mount_point)
     else:
-        if isinstance(app_config_id, basestring):
+        if isinstance(app_config_id, six.string_types):
             app_config_id = ObjectId(app_config_id)
         app_config = model.AppConfig.query.get(_id=app_config_id)
         c.app = p.app_instance(app_config)
@@ -413,7 +413,7 @@ def convert_bools(conf, prefix=''):
     :return: dict
     '''
     def convert_value(val):
-        if isinstance(val, basestring):
+        if isinstance(val, six.string_types):
             if val.strip().lower() == 'true':
                 return True
             elif val.strip().lower() == 'false':
diff --git a/Allura/allura/lib/mail_util.py b/Allura/allura/lib/mail_util.py
index e686502..7a425c5 100644
--- a/Allura/allura/lib/mail_util.py
+++ b/Allura/allura/lib/mail_util.py
@@ -70,7 +70,7 @@ def AddrHeader(fromaddr):
         foo@bar.com
         "Foo Bar" <fo...@bar.com>
     '''
-    if isinstance(fromaddr, basestring) and ' <' in fromaddr:
+    if isinstance(fromaddr, six.string_types) and ' <' in fromaddr:
         name, addr = fromaddr.rsplit(' <', 1)
         addr = '<' + addr  # restore the char we just split off
         addrheader = Header(name, addr)
@@ -274,7 +274,7 @@ class SMTPClient(object):
             message['CC'] = AddrHeader(cc)
             addrs.append(cc)
         if in_reply_to:
-            if not isinstance(in_reply_to, basestring):
+            if not isinstance(in_reply_to, six.string_types):
                 raise TypeError('Only strings are supported now, not lists')
             message['In-Reply-To'] = Header('<%s>' % in_reply_to)
             if not references:
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index e090e71..6e0d9d6 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -1064,7 +1064,7 @@ class ProjectRegistrationProvider(object):
                 tool_config = project_template['tools'][tool]
                 tool_options = tool_config.get('options', {})
                 for k, v in six.iteritems(tool_options):
-                    if isinstance(v, basestring):
+                    if isinstance(v, six.string_types):
                         tool_options[k] = \
                             string.Template(v).safe_substitute(
                                 p.__dict__.get('root_project', {}))
diff --git a/Allura/allura/lib/utils.py b/Allura/allura/lib/utils.py
index 02b8bd0..336383a 100644
--- a/Allura/allura/lib/utils.py
+++ b/Allura/allura/lib/utils.py
@@ -789,7 +789,7 @@ def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
     """
     if strings_only and isinstance(s, (types.NoneType, int)):
         return s
-    elif not isinstance(s, basestring):
+    elif not isinstance(s, six.string_types):
         try:
             return str(s)
         except UnicodeEncodeError:
diff --git a/Allura/allura/lib/validators.py b/Allura/allura/lib/validators.py
index 9c8367b..cd29024 100644
--- a/Allura/allura/lib/validators.py
+++ b/Allura/allura/lib/validators.py
@@ -301,7 +301,7 @@ class UserMapJsonFile(JsonFile):
         value = super(self.__class__, self)._to_python(value, state)
         try:
             for k, v in six.iteritems(value):
-                if not(isinstance(k, basestring) and isinstance(v, basestring)):
+                if not(isinstance(k, six.string_types) and isinstance(v, six.string_types)):
                     raise
             return json.dumps(value) if self.as_string else value
         except:
diff --git a/Allura/allura/lib/widgets/form_fields.py b/Allura/allura/lib/widgets/form_fields.py
index 52c678a..64beee5 100644
--- a/Allura/allura/lib/widgets/form_fields.py
+++ b/Allura/allura/lib/widgets/form_fields.py
@@ -64,7 +64,7 @@ class LabelEdit(ew.InputField):
         placeholder=None)
 
     def from_python(self, value, state=None):
-        if isinstance(value, basestring):
+        if isinstance(value, six.string_types):
             return value
         elif value is None:
             return ''
diff --git a/Allura/allura/model/repository.py b/Allura/allura/model/repository.py
index 2460919..7d34967 100644
--- a/Allura/allura/model/repository.py
+++ b/Allura/allura/model/repository.py
@@ -197,7 +197,7 @@ class RepositoryImplementation(object):
 
     def url_for_commit(self, commit, url_type='ci'):
         'return an URL, given either a commit or object id'
-        if isinstance(commit, basestring):
+        if isinstance(commit, six.string_types):
             object_id = commit
         else:
             object_id = commit._id
diff --git a/Allura/allura/tasks/mail_tasks.py b/Allura/allura/tasks/mail_tasks.py
index 66a870d..c2774af 100644
--- a/Allura/allura/tasks/mail_tasks.py
+++ b/Allura/allura/tasks/mail_tasks.py
@@ -155,7 +155,7 @@ def sendmail(fromaddr, destinations, text, reply_to, subject,
     addrs_multi = []
     if fromaddr is None:
         fromaddr = g.noreply
-    elif not isinstance(fromaddr, basestring) or '@' not in fromaddr:
+    elif not isinstance(fromaddr, six.string_types) or '@' not in fromaddr:
         log.warning('Looking up user with fromaddr: %s', fromaddr)
         user = M.User.query.get(_id=ObjectId(fromaddr), disabled=False, pending=False)
         if not user:
@@ -224,7 +224,7 @@ def sendsimplemail(
     from allura import model as M
     if fromaddr is None:
         fromaddr = g.noreply
-    elif not isinstance(fromaddr, basestring) or '@' not in fromaddr:
+    elif not isinstance(fromaddr, six.string_types) or '@' not in fromaddr:
         log.warning('Looking up user with fromaddr: %s', fromaddr)
         user = M.User.query.get(_id=ObjectId(fromaddr), disabled=False, pending=False)
         if not user:
@@ -233,7 +233,7 @@ def sendsimplemail(
         else:
             fromaddr = user.email_address_header()
 
-    if not isinstance(toaddr, basestring) or '@' not in toaddr:
+    if not isinstance(toaddr, six.string_types) or '@' not in toaddr:
         log.warning('Looking up user with toaddr: %s', toaddr)
         user = M.User.query.get(_id=ObjectId(toaddr), disabled=False, pending=False)
         if not user:
@@ -257,7 +257,7 @@ def send_system_mail_to_user(user_or_emailaddr, subject, text):
     :param subject: subject of the email
     :param text: text of the email (markdown)
     '''
-    if isinstance(user_or_emailaddr, basestring):
+    if isinstance(user_or_emailaddr, six.string_types):
         toaddr = user_or_emailaddr
     else:
         toaddr = user_or_emailaddr._id
diff --git a/AlluraTest/alluratest/validation.py b/AlluraTest/alluratest/validation.py
index df2f246..99065c0 100644
--- a/AlluraTest/alluratest/validation.py
+++ b/AlluraTest/alluratest/validation.py
@@ -260,7 +260,7 @@ class PostParamCheckingTestApp(AntiSpamTestApp):
         if hasattr(params, 'items'):
             params = list(params.items())
         for k, v in params:
-            if not isinstance(k, basestring):
+            if not isinstance(k, six.string_types):
                 raise TypeError('%s key %s is %s, not str' %
                                 (method, k, type(k)))
             self._validate_val(k, v, method)
@@ -269,7 +269,7 @@ class PostParamCheckingTestApp(AntiSpamTestApp):
         if isinstance(v, (list, tuple)):
             for vv in v:
                 self._validate_val(k, vv, method)
-        elif not isinstance(v, (basestring, webtest.forms.File, webtest.forms.Upload)):
+        elif not isinstance(v, (six.string_types, webtest.forms.File, webtest.forms.Upload)):
             raise TypeError(
                 '%s key %s has value %s of type %s, not str. ' %
                 (method, k, v, type(v)))
diff --git a/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py b/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py
index 9355fe6..97ffe9d 100644
--- a/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py
+++ b/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py
@@ -30,6 +30,7 @@ from allura.lib.widgets.forms import CsrfForm
 from allura.lib.widgets.subscriptions import SubscribeForm
 
 from forgediscussion import model as M
+import six
 
 
 class _ThreadsTable(DW._ThreadsTable):
@@ -88,7 +89,7 @@ class _ForumSelector(ew.SingleSelectField):
         return result
 
     def from_python(self, value, state):
-        if isinstance(value, basestring):
+        if isinstance(value, six.string_types):
             return value
         else:
             return value.shortname
diff --git a/ForgeSVN/forgesvn/tests/model/test_repository.py b/ForgeSVN/forgesvn/tests/model/test_repository.py
index 76e97ec..046c17a 100644
--- a/ForgeSVN/forgesvn/tests/model/test_repository.py
+++ b/ForgeSVN/forgesvn/tests/model/test_repository.py
@@ -655,7 +655,7 @@ class _Test(unittest.TestCase):
         repo = getattr(self, 'repo', None)
         t.repo = repo
         for k, v in six.iteritems(kwargs):
-            if isinstance(v, basestring):
+            if isinstance(v, six.string_types):
                 obj = M.repository.Blob(
                     t, k, next(self.idgen))
                 t.blob_ids.append(Object(
diff --git a/ForgeTracker/forgetracker/widgets/ticket_form.py b/ForgeTracker/forgetracker/widgets/ticket_form.py
index b7674ec..4778a36 100644
--- a/ForgeTracker/forgetracker/widgets/ticket_form.py
+++ b/ForgeTracker/forgetracker/widgets/ticket_form.py
@@ -28,6 +28,7 @@ from allura import model as M
 from allura.lib.widgets import form_fields as ffw
 from allura.lib import helpers as h
 from allura.lib import validators as v
+import six
 
 
 class TicketCustomFields(ew.CompoundField):
@@ -90,7 +91,7 @@ class GenericTicketForm(ew.SimpleForm):
         since normally `ProjectUserCombo` shows without any options, and loads
         them asynchronously (via ajax).
         """
-        if isinstance(user, basestring):
+        if isinstance(user, six.string_types):
             user = M.User.by_username(user)
         if user and user != M.User.anonymous():
             field.options = [
diff --git a/scripts/project-import.py b/scripts/project-import.py
index 06df746..584a02f 100644
--- a/scripts/project-import.py
+++ b/scripts/project-import.py
@@ -250,7 +250,7 @@ def create_project(p, nbhd, options):
                 continue
             tool_options = tool_config.get('options', {})
             for k, v in six.iteritems(tool_options):
-                if isinstance(v, basestring):
+                if isinstance(v, six.string_types):
                     tool_options[k] = string.Template(v).safe_substitute(
                         project.root_project.__dict__.get('root_project', {}))
             project.install_app(tool,
diff --git a/scripts/teamforge-import.py b/scripts/teamforge-import.py
index 6c3cad1..0aca4a5 100644
--- a/scripts/teamforge-import.py
+++ b/scripts/teamforge-import.py
@@ -183,7 +183,7 @@ def load_users():
 
 
 def save_user(usernames):
-    if isinstance(usernames, basestring):
+    if isinstance(usernames, six.string_types):
         usernames = [usernames]
 
     load_users()
diff --git a/scripts/trac_import.py b/scripts/trac_import.py
index ef4806d..e9eed3c 100644
--- a/scripts/trac_import.py
+++ b/scripts/trac_import.py
@@ -46,7 +46,7 @@ def main():
                 raise ValueError
             for k, v in six.iteritems(user_map):
                 print(k, v)
-                if not isinstance(k, basestring) or not isinstance(v, basestring):
+                if not isinstance(k, six.string_types) or not isinstance(v, six.string_types):
                     raise ValueError
         except ValueError:
             optparser.error(


[allura] 40/41: [#8349] again: python-modernize -n -w --no-diffs -f import .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit bdcbb9bd3f77fe61317b7d68b17fcaf72023e118
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 17:04:43 2020 -0500

    [#8349] again: python-modernize -n -w --no-diffs -f import .
---
 Allura/allura/version.py                   | 1 +
 ForgeBlog/forgeblog/version.py             | 1 +
 ForgeChat/forgechat/version.py             | 1 +
 ForgeDiscussion/forgediscussion/version.py | 1 +
 ForgeFeedback/forgefeedback/version.py     | 1 +
 ForgeGit/forgegit/version.py               | 1 +
 ForgeLink/forgelink/version.py             | 1 +
 ForgeSVN/forgesvn/version.py               | 1 +
 ForgeTracker/forgetracker/version.py       | 1 +
 ForgeUserStats/forgeuserstats/version.py   | 1 +
 ForgeWiki/forgewiki/version.py             | 1 +
 11 files changed, 11 insertions(+)

diff --git a/Allura/allura/version.py b/Allura/allura/version.py
index 753d37a..dde7f7b 100644
--- a/Allura/allura/version.py
+++ b/Allura/allura/version.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from six.moves import map
 __version_info__ = (0, 1)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeBlog/forgeblog/version.py b/ForgeBlog/forgeblog/version.py
index 7fde7da..927c7dd 100644
--- a/ForgeBlog/forgeblog/version.py
+++ b/ForgeBlog/forgeblog/version.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeChat/forgechat/version.py b/ForgeChat/forgechat/version.py
index 7fde7da..927c7dd 100644
--- a/ForgeChat/forgechat/version.py
+++ b/ForgeChat/forgechat/version.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeDiscussion/forgediscussion/version.py b/ForgeDiscussion/forgediscussion/version.py
index 7fde7da..927c7dd 100644
--- a/ForgeDiscussion/forgediscussion/version.py
+++ b/ForgeDiscussion/forgediscussion/version.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeFeedback/forgefeedback/version.py b/ForgeFeedback/forgefeedback/version.py
index f1464b2..4f74f48 100755
--- a/ForgeFeedback/forgefeedback/version.py
+++ b/ForgeFeedback/forgefeedback/version.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeGit/forgegit/version.py b/ForgeGit/forgegit/version.py
index 7fde7da..927c7dd 100644
--- a/ForgeGit/forgegit/version.py
+++ b/ForgeGit/forgegit/version.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeLink/forgelink/version.py b/ForgeLink/forgelink/version.py
index 7fde7da..927c7dd 100644
--- a/ForgeLink/forgelink/version.py
+++ b/ForgeLink/forgelink/version.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeSVN/forgesvn/version.py b/ForgeSVN/forgesvn/version.py
index 7fde7da..927c7dd 100644
--- a/ForgeSVN/forgesvn/version.py
+++ b/ForgeSVN/forgesvn/version.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeTracker/forgetracker/version.py b/ForgeTracker/forgetracker/version.py
index 7fde7da..927c7dd 100644
--- a/ForgeTracker/forgetracker/version.py
+++ b/ForgeTracker/forgetracker/version.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeUserStats/forgeuserstats/version.py b/ForgeUserStats/forgeuserstats/version.py
index 7fde7da..927c7dd 100644
--- a/ForgeUserStats/forgeuserstats/version.py
+++ b/ForgeUserStats/forgeuserstats/version.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeWiki/forgewiki/version.py b/ForgeWiki/forgewiki/version.py
index 7fde7da..927c7dd 100644
--- a/ForgeWiki/forgewiki/version.py
+++ b/ForgeWiki/forgewiki/version.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from __future__ import unicode_literals
+from __future__ import absolute_import
 from six.moves import map
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))


[allura] 21/41: [#8349] python-modernize -n -w --no-diffs -f filter .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit cd6aea48eed7bffb7c8355375d25a70a698e6c9f
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 14:39:09 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f filter .
---
 Allura/allura/config/app_cfg.py         |  3 ++-
 Allura/allura/controllers/auth.py       |  6 +++---
 Allura/allura/lib/search.py             |  2 +-
 Allura/allura/lib/widgets/forms.py      | 11 ++++++-----
 Allura/allura/model/notification.py     |  3 ++-
 Allura/allura/model/repository.py       |  5 ++---
 Allura/allura/tests/test_app.py         |  2 +-
 AlluraTest/alluratest/test_syntax.py    |  2 +-
 ForgeBlog/forgeblog/command/rssfeeds.py |  3 +--
 ForgeImporters/forgeimporters/base.py   |  1 +
 10 files changed, 20 insertions(+), 18 deletions(-)

diff --git a/Allura/allura/config/app_cfg.py b/Allura/allura/config/app_cfg.py
index 9ba1639..e93b09b 100644
--- a/Allura/allura/config/app_cfg.py
+++ b/Allura/allura/config/app_cfg.py
@@ -47,6 +47,7 @@ import allura
 # needed for tg.configuration to work
 from allura.lib import app_globals, helpers
 from allura.lib.package_path_loader import PackagePathLoader
+from six.moves import filter
 
 log = logging.getLogger(__name__)
 
@@ -106,7 +107,7 @@ class AlluraJinjaRenderer(JinjaRenderer):
             extensions=['jinja2.ext.do', 'jinja2.ext.i18n'])
         jinja2_env.install_gettext_translations(tg.i18n)
         jinja2_env.filters['datetimeformat'] = helpers.datetimeformat
-        jinja2_env.filters['filter'] = lambda s, t=None: filter(t and jinja2_env.tests[t], s)
+        jinja2_env.filters['filter'] = lambda s, t=None: list(filter(t and jinja2_env.tests[t], s))
         jinja2_env.filters['nl2br'] = helpers.nl2br_jinja_filter
         jinja2_env.globals.update({'hasattr': hasattr})
         config['tg.app_globals'].jinja2_env = jinja2_env  # TG doesn't need this, but we use g.jinja2_env a lot
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 44f17d7..145eeab 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -265,7 +265,7 @@ class AuthController(BaseController):
     def send_verification_link(self, a):
         addr = M.EmailAddress.get(email=a, claimed_by_user_id=c.user._id)
         confirmed_emails = M.EmailAddress.find(dict(email=a, confirmed=True)).all()
-        confirmed_emails = filter(lambda item: item != addr, confirmed_emails)
+        confirmed_emails = [item for item in confirmed_emails if item != addr]
 
         if addr:
             if any(email.confirmed for email in confirmed_emails):
@@ -279,7 +279,7 @@ class AuthController(BaseController):
 
     def _verify_addr(self, addr, do_auth_check=True):
         confirmed_by_other = M.EmailAddress.find(dict(email=addr.email, confirmed=True)).all() if addr else []
-        confirmed_by_other = filter(lambda item: item != addr, confirmed_by_other)
+        confirmed_by_other = [item for item in confirmed_by_other if item != addr]
 
         if addr and not confirmed_by_other:
             user = addr.claimed_by_user(include_pending=True)
@@ -597,7 +597,7 @@ class PreferencesController(BaseController):
                     user.email_addresses.append(em.email)
                     em.claimed_by_user_id = user._id
 
-                    confirmed_emails = filter(lambda email: email.confirmed, claimed_emails)
+                    confirmed_emails = [email for email in claimed_emails if email.confirmed]
                     if not confirmed_emails:
                         if not admin:
                             em.send_verification_link()
diff --git a/Allura/allura/lib/search.py b/Allura/allura/lib/search.py
index 6b86179..78922ef 100644
--- a/Allura/allura/lib/search.py
+++ b/Allura/allura/lib/search.py
@@ -321,7 +321,7 @@ def search_app(q='', fq=None, app=True, **kw):
                 else:
                     return doc
 
-            filtered_results = filter(None, imap(filter_unauthorized, results))
+            filtered_results = [_f for _f in imap(filter_unauthorized, results) if _f]
             count -= len(results) - len(filtered_results)
             results = filtered_results
             results = imap(historize_urls, results)
diff --git a/Allura/allura/lib/widgets/forms.py b/Allura/allura/lib/widgets/forms.py
index 67baa1f..45d4a7d 100644
--- a/Allura/allura/lib/widgets/forms.py
+++ b/Allura/allura/lib/widgets/forms.py
@@ -37,6 +37,7 @@ from allura.lib.widgets import form_fields as ffw
 from allura.lib import exceptions as forge_exc
 from allura import model as M
 import six
+from six.moves import filter
 
 
 log = logging.getLogger(__name__)
@@ -288,12 +289,12 @@ class PersonalDataForm(ForgeForm):
 
         self._fields = self.fields
 
-        birthdate_field = filter(lambda x: x.name == 'birthdate', self._fields)
+        birthdate_field = [x for x in self._fields if x.name == 'birthdate']
 
-        sex_field = filter(lambda x: x.name == 'sex', self._fields)[0]
-        country_field = filter(lambda x: x.name == 'country', self._fields)[0]
-        city_field = filter(lambda x: x.name == 'city', self._fields)[0]
-        timezone_field = filter(lambda x: x.name == 'timezone', self._fields)[0]
+        sex_field = [x for x in self._fields if x.name == 'sex'][0]
+        country_field = [x for x in self._fields if x.name == 'country'][0]
+        city_field = [x for x in self._fields if x.name == 'city'][0]
+        timezone_field = [x for x in self._fields if x.name == 'timezone'][0]
 
         for opt in sex_field.options:
             if opt.label == user.sex:
diff --git a/Allura/allura/model/notification.py b/Allura/allura/model/notification.py
index cc67922..4a2cded 100644
--- a/Allura/allura/model/notification.py
+++ b/Allura/allura/model/notification.py
@@ -59,6 +59,7 @@ import allura.tasks.mail_tasks
 from .session import main_orm_session
 from .auth import User, AlluraUserProperty
 import six
+from six.moves import filter
 
 
 log = logging.getLogger(__name__)
@@ -333,7 +334,7 @@ class Notification(MappedClass):
         def perm_check(notification):
             return not (user and artifact) or \
                 security.has_access(artifact, 'read', user)()
-        notifications = filter(perm_check, notifications)
+        notifications = list(filter(perm_check, notifications))
 
         log.debug('Sending digest of notifications [%s] to user %s', ', '.join(
             [n._id for n in notifications]), user_id)
diff --git a/Allura/allura/model/repository.py b/Allura/allura/model/repository.py
index f55f024..b6cafad 100644
--- a/Allura/allura/model/repository.py
+++ b/Allura/allura/model/repository.py
@@ -741,9 +741,8 @@ class Repository(Artifact, ActivityObject):
     @property
     def forks(self):
         all_forks = self.query.find({'upstream_repo.name': self.url()}).all()
-        return filter(lambda fork: fork.app_config is not None
-                      and fork.app_config.project is not None,
-                      all_forks)
+        return [fork for fork in all_forks if fork.app_config is not None
+                      and fork.app_config.project is not None]
 
     def tarball(self, revision, path=None):
         if path:
diff --git a/Allura/allura/tests/test_app.py b/Allura/allura/tests/test_app.py
index 5fc443c..fb41f22 100644
--- a/Allura/allura/tests/test_app.py
+++ b/Allura/allura/tests/test_app.py
@@ -174,6 +174,6 @@ Content-Type: text/html; charset="utf-8"
 --_----------=_150235203132168580--
     """
     msg = mail_util.parse_message(msg_raw)
-    for p in filter(lambda p: p['payload'] != None, msg['parts']):
+    for p in [p for p in msg['parts'] if p['payload'] != None]:
         # filter here mimics logic in `route_email`
         a.handle_artifact_message(ticket, p)
diff --git a/AlluraTest/alluratest/test_syntax.py b/AlluraTest/alluratest/test_syntax.py
index 6e71ebc..74a74ec 100644
--- a/AlluraTest/alluratest/test_syntax.py
+++ b/AlluraTest/alluratest/test_syntax.py
@@ -110,7 +110,7 @@ def create_many_lint_methods():
     py_files = find_stdout.split('\n')
 
     for i, files in enumerate(grouper(40, py_files)):
-        files = filter(None, files)
+        files = [_f for _f in files if _f]
         if not files:
             continue
 
diff --git a/ForgeBlog/forgeblog/command/rssfeeds.py b/ForgeBlog/forgeblog/command/rssfeeds.py
index fa6e04e..d46319a 100644
--- a/ForgeBlog/forgeblog/command/rssfeeds.py
+++ b/ForgeBlog/forgeblog/command/rssfeeds.py
@@ -117,8 +117,7 @@ class RssFeedsCommand(base.BlogCommand):
     def process_entry(self, e, appid):
         title = e.title
         allura_base.log.info(" ...entry '%s'", title)
-        parsed_content = filter(
-            None, e.get('content') or [e.get('summary_detail')])
+        parsed_content = [_f for _f in e.get('content') or [e.get('summary_detail')] if _f]
         if parsed_content:
             content = ''
             for ct in parsed_content:
diff --git a/ForgeImporters/forgeimporters/base.py b/ForgeImporters/forgeimporters/base.py
index edf6aac..4578d95 100644
--- a/ForgeImporters/forgeimporters/base.py
+++ b/ForgeImporters/forgeimporters/base.py
@@ -27,6 +27,7 @@ import traceback
 from six.moves.urllib.parse import urlparse
 from datetime import datetime
 from io import open
+from six.moves import filter
 try:
     from cStringIO import StringIO
 except ImportError:


[allura] 31/41: [#8349] python-modernize -n -w --no-diffs -f itertools_six -f itertools_imports_six .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 01bfc18b2f201a8e2b0b07d5955811b0f1c4e72f
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 15:23:59 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f itertools_six -f itertools_imports_six .
---
 Allura/allura/ext/personal_dashboard/dashboard_main.py |  5 +++--
 Allura/allura/lib/search.py                            | 11 ++++++-----
 AlluraTest/alluratest/test_syntax.py                   |  5 +++--
 ForgeActivity/forgeactivity/main.py                    |  7 ++++---
 4 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/Allura/allura/ext/personal_dashboard/dashboard_main.py b/Allura/allura/ext/personal_dashboard/dashboard_main.py
index 15f9f8f..2df14f0 100644
--- a/Allura/allura/ext/personal_dashboard/dashboard_main.py
+++ b/Allura/allura/ext/personal_dashboard/dashboard_main.py
@@ -21,7 +21,7 @@ import logging
 
 from tg import tmpl_context as c, app_globals as g
 from tg import expose, redirect, config
-from itertools import islice, ifilter
+from itertools import islice
 from ming.orm import session
 
 from allura.model.timeline import perm_check, get_activity_object
@@ -30,6 +30,7 @@ from allura.controllers.feed import FeedController
 from allura.lib.widgets.user_profile import SectionBase, SectionsUtil, ProjectsSectionBase
 from allura.lib.widgets import form_fields as ffw
 from paste.deploy.converters import asbool
+from six.moves import filter
 
 log = logging.getLogger(__name__)
 
@@ -152,7 +153,7 @@ class ActivitySection(DashboardSectionBase):
             self.user, page=0, limit=100,
             actor_only=False,
         )
-        filtered_timeline = list(islice(ifilter(perm_check(c.user), full_timeline),
+        filtered_timeline = list(islice(filter(perm_check(c.user), full_timeline),
                                         0, 8))
         for activity in filtered_timeline:
             # Get the project for the activity.obj so we can use it in the
diff --git a/Allura/allura/lib/search.py b/Allura/allura/lib/search.py
index 78922ef..4c5dab9 100644
--- a/Allura/allura/lib/search.py
+++ b/Allura/allura/lib/search.py
@@ -20,7 +20,7 @@ from __future__ import absolute_import
 import re
 import socket
 from logging import getLogger
-from itertools import imap
+
 
 import bson
 import markdown
@@ -34,6 +34,7 @@ from allura.lib import helpers as h
 from allura.lib.solr import escape_solr_arg
 from allura.lib.utils import urlencode
 import six
+from six.moves import map
 
 log = getLogger(__name__)
 
@@ -321,12 +322,12 @@ def search_app(q='', fq=None, app=True, **kw):
                 else:
                     return doc
 
-            filtered_results = [_f for _f in imap(filter_unauthorized, results) if _f]
+            filtered_results = [_f for _f in map(filter_unauthorized, results) if _f]
             count -= len(results) - len(filtered_results)
             results = filtered_results
-            results = imap(historize_urls, results)
-            results = imap(add_matches, results)
-            results = imap(paginate_comment_urls, results)
+            results = map(historize_urls, results)
+            results = map(add_matches, results)
+            results = map(paginate_comment_urls, results)
 
     # Provide sort urls to the view
     score_url = 'score desc'
diff --git a/AlluraTest/alluratest/test_syntax.py b/AlluraTest/alluratest/test_syntax.py
index 74a74ec..db3621c 100644
--- a/AlluraTest/alluratest/test_syntax.py
+++ b/AlluraTest/alluratest/test_syntax.py
@@ -20,8 +20,9 @@ from __future__ import absolute_import
 import os.path
 from subprocess import Popen, PIPE
 import sys
-from itertools import izip_longest
+
 from unittest import SkipTest
+from six.moves import zip_longest
 
 toplevel_dir = os.path.abspath(os.path.dirname(__file__) + "/../..")
 
@@ -42,7 +43,7 @@ find_py = "find Allura Forge* -name '*.py'"
 def grouper(n, iterable, fillvalue=None):
     "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
     args = [iter(iterable)] * n
-    return izip_longest(fillvalue=fillvalue, *args)
+    return zip_longest(fillvalue=fillvalue, *args)
 
 
 def test_no_local_tz_functions():
diff --git a/ForgeActivity/forgeactivity/main.py b/ForgeActivity/forgeactivity/main.py
index 4888fa7..5f1c78b 100644
--- a/ForgeActivity/forgeactivity/main.py
+++ b/ForgeActivity/forgeactivity/main.py
@@ -20,7 +20,7 @@ from __future__ import absolute_import
 import logging
 import calendar
 from datetime import timedelta
-from itertools import islice, ifilter
+from itertools import islice
 
 from bson import ObjectId
 from ming.orm import session
@@ -46,6 +46,7 @@ from allura.lib.widgets.form_fields import PageList
 from allura.ext.user_profile import ProfileSectionBase
 
 from .widgets.follow import FollowToggle
+from six.moves import filter
 
 log = logging.getLogger(__name__)
 
@@ -123,7 +124,7 @@ class ForgeActivityController(BaseController):
         timeline = g.director.get_timeline(followee, page,
                                            limit=extra_limit,
                                            actor_only=actor_only)
-        filtered_timeline = list(islice(ifilter(perm_check(c.user), timeline),
+        filtered_timeline = list(islice(filter(perm_check(c.user), timeline),
                                         0, limit))
         if extra_limit == limit:
             # if we didn't ask for extra, then we expect there's more if we got all we asked for
@@ -290,7 +291,7 @@ class ForgeActivityProfileSection(ProfileSectionBase):
             self.user, page=0, limit=100,
             actor_only=True,
         )
-        filtered_timeline = list(islice(ifilter(perm_check(c.user), full_timeline),
+        filtered_timeline = list(islice(filter(perm_check(c.user), full_timeline),
                                         0, 8))
         for activity in filtered_timeline:
             # Get the project for the activity.obj so we can use it in the


[allura] 09/41: [#8349] python-modernize -n -w --no-diffs -f imports_six -f urllib_six .

Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8349
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 0d24f7e7402529fef37ee56e902333a7a2359950
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Feb 10 12:47:22 2020 -0500

    [#8349] python-modernize -n -w --no-diffs -f imports_six -f urllib_six .
---
 Allura/allura/command/taskd.py                       |  2 +-
 Allura/allura/config/middleware.py                   |  2 +-
 Allura/allura/controllers/attachments.py             |  2 +-
 Allura/allura/controllers/auth.py                    |  2 +-
 Allura/allura/controllers/basetest_project_root.py   |  2 +-
 Allura/allura/controllers/discuss.py                 |  2 +-
 Allura/allura/controllers/project.py                 |  2 +-
 Allura/allura/controllers/repository.py              |  2 +-
 Allura/allura/controllers/rest.py                    |  2 +-
 Allura/allura/controllers/site_admin.py              |  2 +-
 Allura/allura/ext/admin/admin_main.py                |  2 +-
 Allura/allura/lib/app_globals.py                     |  2 +-
 Allura/allura/lib/custom_middleware.py               |  2 +-
 Allura/allura/lib/decorators.py                      |  4 ++--
 Allura/allura/lib/gravatar.py                        |  4 ++--
 Allura/allura/lib/helpers.py                         | 18 +++++++++---------
 Allura/allura/lib/import_api.py                      | 16 ++++++++--------
 Allura/allura/lib/macro.py                           |  6 +++---
 Allura/allura/lib/markdown_extensions.py             |  2 +-
 Allura/allura/lib/phone/nexmo.py                     |  2 +-
 Allura/allura/lib/plugin.py                          |  4 ++--
 Allura/allura/lib/repository.py                      |  2 +-
 Allura/allura/lib/utils.py                           |  6 +++---
 Allura/allura/model/auth.py                          |  2 +-
 Allura/allura/model/index.py                         |  4 ++--
 Allura/allura/model/project.py                       |  6 +++---
 Allura/allura/model/repo_refresh.py                  |  2 +-
 Allura/allura/model/repository.py                    |  4 ++--
 Allura/allura/scripts/trac_export.py                 | 12 ++++++------
 Allura/allura/tasks/mail_tasks.py                    |  4 ++--
 Allura/allura/tests/functional/test_auth.py          |  4 ++--
 Allura/allura/tests/functional/test_gravatar.py      |  2 +-
 Allura/allura/tests/functional/test_neighborhood.py  |  4 ++--
 Allura/allura/tests/functional/test_root.py          |  2 +-
 Allura/allura/tests/test_helpers.py                  |  8 ++++----
 Allura/allura/tests/unit/spam/test_akismet.py        |  4 ++--
 Allura/ldap-setup.py                                 |  2 +-
 AlluraTest/alluratest/controller.py                  |  4 ++--
 AlluraTest/alluratest/validation.py                  |  6 +++---
 ForgeBlog/forgeblog/main.py                          |  6 +++---
 ForgeChat/forgechat/command.py                       |  2 +-
 ForgeDiscussion/forgediscussion/controllers/root.py  |  2 +-
 ForgeDiscussion/forgediscussion/forum_main.py        |  4 ++--
 ForgeFeedback/forgefeedback/model/feedback.py        |  2 +-
 ForgeImporters/forgeimporters/base.py                | 10 +++++-----
 ForgeImporters/forgeimporters/github/__init__.py     |  4 ++--
 ForgeImporters/forgeimporters/github/tracker.py      |  2 +-
 .../forgeimporters/tests/github/test_extractor.py    |  4 ++--
 .../forgeimporters/tests/github/test_tracker.py      |  2 +-
 ForgeTracker/forgetracker/model/ticket.py            |  4 ++--
 .../forgetracker/tests/functional/test_root.py       |  2 +-
 .../forgetracker/tests/unit/test_ticket_model.py     |  4 ++--
 ForgeTracker/forgetracker/tracker_main.py            |  2 +-
 ForgeWiki/forgewiki/wiki_main.py                     |  2 +-
 fuse/accessfs.py                                     |  8 ++++----
 scripts/teamforge-import.py                          | 16 ++++++++--------
 scripts/wiki-copy.py                                 | 20 ++++++++++----------
 57 files changed, 128 insertions(+), 128 deletions(-)

diff --git a/Allura/allura/command/taskd.py b/Allura/allura/command/taskd.py
index b4c97d8..908a45e 100644
--- a/Allura/allura/command/taskd.py
+++ b/Allura/allura/command/taskd.py
@@ -21,7 +21,7 @@ from __future__ import absolute_import
 import logging
 import os
 import time
-import Queue
+import six.moves.queue
 from contextlib import contextmanager
 from datetime import datetime, timedelta
 import signal
diff --git a/Allura/allura/config/middleware.py b/Allura/allura/config/middleware.py
index 8c63f79..83690bc 100644
--- a/Allura/allura/config/middleware.py
+++ b/Allura/allura/config/middleware.py
@@ -230,7 +230,7 @@ def allura_globals_middleware(app):
 def get_tg_vars(context):
     import tg
     from allura.lib import helpers as h
-    from urllib import quote, quote_plus
+    from six.moves.urllib.parse import quote, quote_plus
     context.setdefault('g', tg.app_globals)
     context.setdefault('c', tg.tmpl_context)
     context.setdefault('h', h)
diff --git a/Allura/allura/controllers/attachments.py b/Allura/allura/controllers/attachments.py
index e57e16a..427a329 100644
--- a/Allura/allura/controllers/attachments.py
+++ b/Allura/allura/controllers/attachments.py
@@ -17,7 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import absolute_import
-from urllib import unquote
+from six.moves.urllib.parse import unquote
 from webob import exc
 
 from tg import expose, request, redirect
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 496232c..3ec037e 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -21,7 +21,7 @@ import logging
 import os
 from datetime import datetime, timedelta
 import re
-from urlparse import urlparse, urljoin
+from six.moves.urllib.parse import urlparse, urljoin
 
 import bson
 import tg
diff --git a/Allura/allura/controllers/basetest_project_root.py b/Allura/allura/controllers/basetest_project_root.py
index 89a3168..5364cb4 100644
--- a/Allura/allura/controllers/basetest_project_root.py
+++ b/Allura/allura/controllers/basetest_project_root.py
@@ -21,7 +21,7 @@
 from __future__ import unicode_literals
 from __future__ import absolute_import
 import logging
-from urllib import unquote
+from six.moves.urllib.parse import unquote
 
 from tg import tmpl_context as c
 from tg import request
diff --git a/Allura/allura/controllers/discuss.py b/Allura/allura/controllers/discuss.py
index c3c4d1b..f918538 100644
--- a/Allura/allura/controllers/discuss.py
+++ b/Allura/allura/controllers/discuss.py
@@ -17,7 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import absolute_import
-from urllib import unquote
+from six.moves.urllib.parse import unquote
 from datetime import datetime
 import logging
 
diff --git a/Allura/allura/controllers/project.py b/Allura/allura/controllers/project.py
index f8fd627..44cf619 100644
--- a/Allura/allura/controllers/project.py
+++ b/Allura/allura/controllers/project.py
@@ -20,7 +20,7 @@ from __future__ import absolute_import
 import re
 import logging
 from datetime import datetime, timedelta
-from urllib import unquote
+from six.moves.urllib.parse import unquote
 
 from bson import ObjectId
 from tg import expose, flash, redirect, validate, request, config, session
diff --git a/Allura/allura/controllers/repository.py b/Allura/allura/controllers/repository.py
index 93d746f..3c9d191 100644
--- a/Allura/allura/controllers/repository.py
+++ b/Allura/allura/controllers/repository.py
@@ -21,7 +21,7 @@ import os
 import logging
 import difflib
 from datetime import datetime
-from urllib import quote, unquote
+from six.moves.urllib.parse import quote, unquote
 from collections import defaultdict, OrderedDict
 
 
diff --git a/Allura/allura/controllers/rest.py b/Allura/allura/controllers/rest.py
index 7e12731..7977432 100644
--- a/Allura/allura/controllers/rest.py
+++ b/Allura/allura/controllers/rest.py
@@ -21,7 +21,7 @@
 from __future__ import unicode_literals
 from __future__ import absolute_import
 import logging
-from urllib import unquote
+from six.moves.urllib.parse import unquote
 
 import oauth2 as oauth
 from paste.util.converters import asbool
diff --git a/Allura/allura/controllers/site_admin.py b/Allura/allura/controllers/site_admin.py
index 1d1d158..96399b9 100644
--- a/Allura/allura/controllers/site_admin.py
+++ b/Allura/allura/controllers/site_admin.py
@@ -49,7 +49,7 @@ from allura.command.show_models import dfs, build_model_inheritance_graph
 from allura.scripts.delete_projects import DeleteProjects
 import allura
 
-from urlparse import urlparse
+from six.moves.urllib.parse import urlparse
 from webhelpers import paginate
 
 
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index 79544f3..631c415 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -23,7 +23,7 @@ import os
 from random import randint
 from collections import OrderedDict
 from datetime import datetime
-from urlparse import urlparse
+from six.moves.urllib.parse import urlparse
 import json
 from operator import itemgetter, attrgetter
 import pkg_resources
diff --git a/Allura/allura/lib/app_globals.py b/Allura/allura/lib/app_globals.py
index f6a85e4..f809a60 100644
--- a/Allura/allura/lib/app_globals.py
+++ b/Allura/allura/lib/app_globals.py
@@ -27,7 +27,7 @@ import cgi
 import hashlib
 import json
 import datetime
-from urllib import urlencode
+from six.moves.urllib.parse import urlencode
 from subprocess import Popen, PIPE
 import os
 import time
diff --git a/Allura/allura/lib/custom_middleware.py b/Allura/allura/lib/custom_middleware.py
index 86d5d02..b1fd554 100644
--- a/Allura/allura/lib/custom_middleware.py
+++ b/Allura/allura/lib/custom_middleware.py
@@ -295,7 +295,7 @@ class AlluraTimerMiddleware(TimerMiddleware):
         import ming
         import pymongo
         import socket
-        import urllib2
+        import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
         import activitystream
         import pygments
         import difflib
diff --git a/Allura/allura/lib/decorators.py b/Allura/allura/lib/decorators.py
index f018fa3..3ce0f18 100644
--- a/Allura/allura/lib/decorators.py
+++ b/Allura/allura/lib/decorators.py
@@ -21,9 +21,9 @@ import inspect
 import sys
 import json
 import logging
-from Cookie import Cookie
+from six.moves.http_cookies import Cookie
 from collections import defaultdict
-from urllib import unquote
+from six.moves.urllib.parse import unquote
 from datetime import datetime
 from datetime import timedelta
 
diff --git a/Allura/allura/lib/gravatar.py b/Allura/allura/lib/gravatar.py
index 9639b87..60178f9 100644
--- a/Allura/allura/lib/gravatar.py
+++ b/Allura/allura/lib/gravatar.py
@@ -18,7 +18,7 @@
 from __future__ import unicode_literals
 from __future__ import absolute_import
 import re
-import urllib
+import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
 import hashlib
 
 from tg import config
@@ -88,7 +88,7 @@ def url(email=None, gravatar_id=None, **kw):
         kw['r'] = 'pg'
     if 'd' not in kw and config.get('default_avatar_image'):
         kw['d'] = h.absurl(config['default_avatar_image'])
-    return ('https://secure.gravatar.com/avatar/%s?%s' % (gravatar_id, urllib.urlencode(kw)))
+    return ('https://secure.gravatar.com/avatar/%s?%s' % (gravatar_id, six.moves.urllib.parse.urlencode(kw)))
 
 
 def for_user(user):
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index a2fc96a..d874a0d 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -23,15 +23,15 @@ import sys
 import os
 import os.path
 import difflib
-import urllib
-import urllib2
+import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
+import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
 import re
 import unicodedata
 import json
 import logging
 import string
 import random
-import cPickle as pickle
+import six.moves.cPickle as pickle
 from hashlib import sha1
 from datetime import datetime, timedelta
 from collections import defaultdict
@@ -167,16 +167,16 @@ def monkeypatch(*objs):
 
 def urlquote(url, safe=b"/"):
     try:
-        return urllib.quote(str(url), safe=safe)
+        return six.moves.urllib.parse.quote(str(url), safe=safe)
     except UnicodeEncodeError:
-        return urllib.quote(url.encode('utf-8'), safe=safe)
+        return six.moves.urllib.parse.quote(url.encode('utf-8'), safe=safe)
 
 
 def urlquoteplus(url, safe=b""):
     try:
-        return urllib.quote_plus(str(url), safe=safe)
+        return six.moves.urllib.parse.quote_plus(str(url), safe=safe)
     except UnicodeEncodeError:
-        return urllib.quote_plus(url.encode('utf-8'), safe=safe)
+        return six.moves.urllib.parse.quote_plus(url.encode('utf-8'), safe=safe)
 
 
 def urlquote_path_only(url):
@@ -1005,9 +1005,9 @@ def urlopen(url, retries=3, codes=(408, 500, 502, 503, 504), timeout=None):
     attempts = 0
     while True:
         try:
-            return urllib2.urlopen(url, timeout=timeout)
+            return six.moves.urllib.request.urlopen(url, timeout=timeout)
         except IOError as e:
-            no_retry = isinstance(e, urllib2.HTTPError) and e.code not in codes
+            no_retry = isinstance(e, six.moves.urllib.error.HTTPError) and e.code not in codes
             if attempts < retries and not no_retry:
                 attempts += 1
                 continue
diff --git a/Allura/allura/lib/import_api.py b/Allura/allura/lib/import_api.py
index f061fed..7a8a6bd 100644
--- a/Allura/allura/lib/import_api.py
+++ b/Allura/allura/lib/import_api.py
@@ -17,9 +17,9 @@
 
 from __future__ import unicode_literals
 from __future__ import absolute_import
-import urllib
-import urllib2
-import urlparse
+import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
+import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
+import six.moves.urllib.parse
 import hmac
 import hashlib
 import json
@@ -42,24 +42,24 @@ class AlluraImportApiClient(object):
         return params
 
     def call(self, url, **params):
-        url = urlparse.urljoin(self.base_url, url)
+        url = six.moves.urllib.parse.urljoin(self.base_url, url)
         if self.verbose:
             log.info("Import API URL: %s", url)
 
-        params = self.sign(urlparse.urlparse(url).path, params.items())
+        params = self.sign(six.moves.urllib.parse.urlparse(url).path, params.items())
 
         while True:
             try:
-                result = urllib2.urlopen(url, urllib.urlencode(params))
+                result = six.moves.urllib.request.urlopen(url, six.moves.urllib.parse.urlencode(params))
                 resp = result.read()
                 return json.loads(resp)
-            except urllib2.HTTPError as e:
+            except six.moves.urllib.error.HTTPError as e:
                 e.msg += ' ({0})'.format(url)
                 if self.verbose:
                     error_content = e.read()
                     e.msg += '. Error response:\n' + error_content
                 raise e
-            except (urllib2.URLError, IOError):
+            except (six.moves.urllib.error.URLError, IOError):
                 if self.retry:
                     log.exception('Error making API request, will retry')
                     continue
diff --git a/Allura/allura/lib/macro.py b/Allura/allura/lib/macro.py
index 016fbfe..c8dc885 100644
--- a/Allura/allura/lib/macro.py
+++ b/Allura/allura/lib/macro.py
@@ -22,12 +22,12 @@ import random
 import shlex
 import logging
 import traceback
-import urllib2
+import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
 
 import oembed
 import jinja2
 from operator import attrgetter
-from urlparse import urlparse, urlunparse
+from six.moves.urllib.parse import urlparse, urlunparse
 
 import pymongo
 from tg import tmpl_context as c, app_globals as g
@@ -466,7 +466,7 @@ def embed(url=None):
             html = consumer.embed(url)['html']
         except oembed.OEmbedNoEndpoint:
             html = None
-        except urllib2.HTTPError as e:
+        except six.moves.urllib.error.HTTPError as e:
             if e.code == 404:
                 return 'Video not available'
             else:
diff --git a/Allura/allura/lib/markdown_extensions.py b/Allura/allura/lib/markdown_extensions.py
index eb876d3..0e12187 100644
--- a/Allura/allura/lib/markdown_extensions.py
+++ b/Allura/allura/lib/markdown_extensions.py
@@ -21,7 +21,7 @@ from __future__ import unicode_literals
 from __future__ import absolute_import
 import re
 import logging
-from urlparse import urljoin
+from six.moves.urllib.parse import urljoin
 
 from tg import config
 from bs4 import BeautifulSoup
diff --git a/Allura/allura/lib/phone/nexmo.py b/Allura/allura/lib/phone/nexmo.py
index 9b4d338..f251c93 100644
--- a/Allura/allura/lib/phone/nexmo.py
+++ b/Allura/allura/lib/phone/nexmo.py
@@ -18,7 +18,7 @@
 from __future__ import unicode_literals
 from __future__ import absolute_import
 import logging
-from urlparse import urljoin
+from six.moves.urllib.parse import urljoin
 import cgi
 import json
 
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index 085726b..4f80a58 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -27,8 +27,8 @@ import subprocess
 import string
 import crypt
 import random
-from urllib2 import urlopen
-from urlparse import urlparse
+from six.moves.urllib.request import urlopen
+from six.moves.urllib.parse import urlparse
 from cStringIO import StringIO
 from random import randint
 from hashlib import sha256
diff --git a/Allura/allura/lib/repository.py b/Allura/allura/lib/repository.py
index 1ff9778..2ad3a5a 100644
--- a/Allura/allura/lib/repository.py
+++ b/Allura/allura/lib/repository.py
@@ -18,7 +18,7 @@
 from __future__ import unicode_literals
 from __future__ import absolute_import
 import logging
-from urllib import quote
+from six.moves.urllib.parse import quote
 
 from tg import tmpl_context as c, app_globals as g
 from tg import request
diff --git a/Allura/allura/lib/utils.py b/Allura/allura/lib/utils.py
index 6e2322c..8e42ae2 100644
--- a/Allura/allura/lib/utils.py
+++ b/Allura/allura/lib/utils.py
@@ -35,8 +35,8 @@ import magic
 from itertools import groupby
 import operator as op
 import collections
-from urlparse import urlparse
-import urllib
+from six.moves.urllib.parse import urlparse
+import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
 import types
 import socket
 
@@ -820,7 +820,7 @@ def urlencode(params):
     unicode strings. The parameters are first case to UTF-8 encoded strings and
     then encoded as per normal.
     """
-    return urllib.urlencode([i for i in generate_smart_str(params)])
+    return six.moves.urllib.parse.urlencode([i for i in generate_smart_str(params)])
 
 
 def close_ipv4_addrs(ip1, ip2):
diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index 28fc1b8..c951edf 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -19,7 +19,7 @@ from __future__ import unicode_literals
 from __future__ import absolute_import
 import logging
 import calendar
-from urlparse import urlparse
+from six.moves.urllib.parse import urlparse
 from email import header
 from hashlib import sha256
 from datetime import timedelta, datetime, time
diff --git a/Allura/allura/model/index.py b/Allura/allura/model/index.py
index b55e186..47c6ddb 100644
--- a/Allura/allura/model/index.py
+++ b/Allura/allura/model/index.py
@@ -20,9 +20,9 @@ from __future__ import absolute_import
 import re
 import logging
 from itertools import groupby
-from cPickle import dumps, loads
+from six.moves.cPickle import dumps, loads
 from collections import defaultdict
-from urllib import unquote
+from six.moves.urllib.parse import unquote
 
 import bson
 import pymongo
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index d8d1764..97319e3 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -23,7 +23,7 @@ from calendar import timegm
 from collections import Counter, OrderedDict
 from datetime import datetime
 from copy import deepcopy
-import urllib
+import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
 import re
 from xml.etree import ElementTree as ET
 
@@ -1188,10 +1188,10 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
             screenshots=[
                 dict(
                     url=h.absurl(self.url() + 'screenshot/' +
-                                 urllib.quote(ss.filename.encode('utf8'))),
+                                 six.moves.urllib.parse.quote(ss.filename.encode('utf8'))),
                     thumbnail_url=h.absurl(
                         self.url(
-                        ) + 'screenshot/' + urllib.quote(ss.filename.encode('utf8')) + '/thumb'),
+                        ) + 'screenshot/' + six.moves.urllib.parse.quote(ss.filename.encode('utf8')) + '/thumb'),
                     caption=ss.caption,
                 )
                 for ss in self.get_screenshots()
diff --git a/Allura/allura/model/repo_refresh.py b/Allura/allura/model/repo_refresh.py
index 74c005d..49d911b 100644
--- a/Allura/allura/model/repo_refresh.py
+++ b/Allura/allura/model/repo_refresh.py
@@ -19,7 +19,7 @@ from __future__ import unicode_literals
 from __future__ import absolute_import
 import logging
 from itertools import chain
-from cPickle import dumps
+from six.moves.cPickle import dumps
 from collections import OrderedDict
 
 import bson
diff --git a/Allura/allura/model/repository.py b/Allura/allura/model/repository.py
index 44adc5e..ac80114 100644
--- a/Allura/allura/model/repository.py
+++ b/Allura/allura/model/repository.py
@@ -28,9 +28,9 @@ from hashlib import sha1
 from datetime import datetime, timedelta
 from time import time
 from collections import defaultdict, OrderedDict
-from urlparse import urljoin
+from six.moves.urllib.parse import urljoin
 from threading import Thread
-from Queue import Queue
+from six.moves.queue import Queue
 from itertools import chain, islice
 from difflib import SequenceMatcher
 
diff --git a/Allura/allura/scripts/trac_export.py b/Allura/allura/scripts/trac_export.py
index d2180e8..bbdde95 100644
--- a/Allura/allura/scripts/trac_export.py
+++ b/Allura/allura/scripts/trac_export.py
@@ -23,8 +23,8 @@ from __future__ import absolute_import
 import logging
 import sys
 import csv
-import urlparse
-import urllib2
+import six.moves.urllib.parse
+import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
 import json
 import time
 import re
@@ -43,7 +43,7 @@ except ImportError:
     try:
         from allura.lib.helpers import urlopen
     except ImportError:
-        from urllib2 import urlopen
+        from six.moves.urllib.request import urlopen
 
 log = logging.getLogger(__name__)
 
@@ -115,7 +115,7 @@ class TracExport(object):
         return out
 
     def full_url(self, suburl, type=None):
-        url = urlparse.urljoin(self.base_url, suburl)
+        url = six.moves.urllib.parse.urljoin(self.base_url, suburl)
         if type is None:
             return url
         glue = '&' if '?' in suburl else '?'
@@ -146,7 +146,7 @@ class TracExport(object):
         # telling that access denied. So, we'll emulate 403 ourselves.
         # TODO: currently, any non-csv result treated as 403.
         if not f.info()['Content-Type'].startswith('text/csv'):
-            raise urllib2.HTTPError(
+            raise six.moves.urllib.error.HTTPError(
                 url, 403, 'Forbidden - emulated', f.info(), f)
         return f
 
@@ -254,7 +254,7 @@ class TracExport(object):
         url = self.full_url(self.QUERY_BY_PAGE_URL % self.page, 'csv')
         try:
             f = self.csvopen(url)
-        except urllib2.HTTPError as e:
+        except six.moves.urllib.error.HTTPError as e:
             if 'emulated' in e.msg:
                 body = e.fp.read()
                 if 'beyond the number of pages in the query' in six.ensure_text(body):
diff --git a/Allura/allura/tasks/mail_tasks.py b/Allura/allura/tasks/mail_tasks.py
index d3827ae..66a870d 100644
--- a/Allura/allura/tasks/mail_tasks.py
+++ b/Allura/allura/tasks/mail_tasks.py
@@ -18,7 +18,7 @@
 from __future__ import unicode_literals
 from __future__ import absolute_import
 import logging
-import HTMLParser
+import six.moves.html_parser
 import re
 
 from tg import tmpl_context as c, app_globals as g, config
@@ -128,7 +128,7 @@ def create_multipart_msg(text, metalink=None):
                         plain_text,
                         flags=re.DOTALL,  # match newlines too
                         )
-    plain_text = HTMLParser.HTMLParser().unescape(plain_text)  # put literal HTML tags back into plaintext
+    plain_text = six.moves.html_parser.HTMLParser().unescape(plain_text)  # put literal HTML tags back into plaintext
     plain_msg = mail_util.encode_email_part(plain_text, 'plain')
 
     html_text = g.forge_markdown(email=True).convert(text)
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index 0cef79e..def21d4 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -22,8 +22,8 @@ import calendar
 from datetime import datetime, time, timedelta
 from time import time as time_time
 import json
-from urlparse import urlparse, parse_qs
-from urllib import urlencode
+from six.moves.urllib.parse import urlparse, parse_qs
+from six.moves.urllib.parse import urlencode
 
 from bson import ObjectId
 import re
diff --git a/Allura/allura/tests/functional/test_gravatar.py b/Allura/allura/tests/functional/test_gravatar.py
index f2235ed..7120de1 100644
--- a/Allura/allura/tests/functional/test_gravatar.py
+++ b/Allura/allura/tests/functional/test_gravatar.py
@@ -17,7 +17,7 @@
 
 from __future__ import unicode_literals
 from __future__ import absolute_import
-from urlparse import urlparse, parse_qs
+from six.moves.urllib.parse import urlparse, parse_qs
 
 import tg
 from nose.tools import assert_equal
diff --git a/Allura/allura/tests/functional/test_neighborhood.py b/Allura/allura/tests/functional/test_neighborhood.py
index 5ed2a2a..fd4e29b 100644
--- a/Allura/allura/tests/functional/test_neighborhood.py
+++ b/Allura/allura/tests/functional/test_neighborhood.py
@@ -21,7 +21,7 @@ from __future__ import absolute_import
 import json
 import os
 from cStringIO import StringIO
-import urllib2
+import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
 
 import PIL
 from mock import patch
@@ -598,7 +598,7 @@ class TestNeighborhood(TestController):
             antispam=True,
             extra_environ=dict(username=str('root')))
         cookies = r.headers.getall('Set-Cookie')
-        flash_msg_cookies = map(urllib2.unquote, cookies)
+        flash_msg_cookies = map(six.moves.urllib.parse.unquote, cookies)
 
         assert any('Internal Error' in cookie for cookie in flash_msg_cookies)
 
diff --git a/Allura/allura/tests/functional/test_root.py b/Allura/allura/tests/functional/test_root.py
index 322f2bb..15caa36 100644
--- a/Allura/allura/tests/functional/test_root.py
+++ b/Allura/allura/tests/functional/test_root.py
@@ -31,7 +31,7 @@ Please read http://pythonpaste.org/webtest/ for more information.
 from __future__ import unicode_literals
 from __future__ import absolute_import
 import os
-from urllib import quote
+from six.moves.urllib.parse import quote
 
 from tg import tmpl_context as c
 from nose.tools import assert_equal, assert_in
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index 0c6d321..0308f17 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -441,8 +441,8 @@ class TestUrlOpen(TestCase):
     @patch('allura.lib.helpers.urllib2')
     def test_no_error(self, urllib2):
         r = h.urlopen('myurl')
-        self.assertEqual(r, urllib2.urlopen.return_value)
-        urllib2.urlopen.assert_called_once_with('myurl', timeout=None)
+        self.assertEqual(r, six.moves.urllib.request.urlopen.return_value)
+        six.moves.urllib.request.urlopen.assert_called_once_with('myurl', timeout=None)
 
     @patch('allura.lib.helpers.urllib2.urlopen')
     def test_socket_timeout(self, urlopen):
@@ -467,7 +467,7 @@ class TestUrlOpen(TestCase):
 
     @patch('allura.lib.helpers.urllib2.urlopen')
     def test_handled_http_error(self, urlopen):
-        from urllib2 import HTTPError
+        from six.moves.urllib.error import HTTPError
 
         def side_effect(url, timeout=None):
             raise HTTPError('url', 408, 'timeout', None, None)
@@ -477,7 +477,7 @@ class TestUrlOpen(TestCase):
 
     @patch('allura.lib.helpers.urllib2.urlopen')
     def test_unhandled_http_error(self, urlopen):
-        from urllib2 import HTTPError
+        from six.moves.urllib.error import HTTPError
 
         def side_effect(url, timeout=None):
             raise HTTPError('url', 404, 'timeout', None, None)
diff --git a/Allura/allura/tests/unit/spam/test_akismet.py b/Allura/allura/tests/unit/spam/test_akismet.py
index c69eb51..670c98f 100644
--- a/Allura/allura/tests/unit/spam/test_akismet.py
+++ b/Allura/allura/tests/unit/spam/test_akismet.py
@@ -22,7 +22,7 @@ from __future__ import unicode_literals
 from __future__ import absolute_import
 import mock
 import unittest
-import urllib
+import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
 from datetime import datetime
 
 from bson import ObjectId
@@ -40,7 +40,7 @@ class TestAkismet(unittest.TestCase):
         def side_effect(*args, **kw):
             # side effect to test that data being sent to
             # akismet can be successfully urlencoded
-            urllib.urlencode(kw.get('data', {}))
+            six.moves.urllib.parse.urlencode(kw.get('data', {}))
         self.akismet.service.comment_check = mock.Mock(side_effect=side_effect)
         self.akismet.service.submit_spam = mock.Mock(side_effect=side_effect)
         self.akismet.service.submit_ham = mock.Mock(side_effect=side_effect)
diff --git a/Allura/ldap-setup.py b/Allura/ldap-setup.py
index 8ff17c4..fcd79ce 100644
--- a/Allura/ldap-setup.py
+++ b/Allura/ldap-setup.py
@@ -25,7 +25,7 @@ import string
 import logging
 from contextlib import contextmanager
 from tempfile import mkstemp
-from ConfigParser import ConfigParser, NoOptionError
+from six.moves.configparser import ConfigParser, NoOptionError
 
 logging.basicConfig(level=logging.DEBUG)
 log = logging.getLogger('ldap-setup')
diff --git a/AlluraTest/alluratest/controller.py b/AlluraTest/alluratest/controller.py
index bb7fd89..b1c48b4 100644
--- a/AlluraTest/alluratest/controller.py
+++ b/AlluraTest/alluratest/controller.py
@@ -19,7 +19,7 @@
 from __future__ import unicode_literals
 from __future__ import absolute_import
 import os
-import urllib
+import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
 import json
 
 import mock
@@ -193,7 +193,7 @@ class TestController(object):
 
     def webflash(self, response):
         "Extract webflash content from current state of WebTest app"
-        return urllib.unquote(self.app.cookies.get('webflash', ''))
+        return six.moves.urllib.parse.unquote(self.app.cookies.get('webflash', ''))
 
     def subscription_options(self, response):
         """
diff --git a/AlluraTest/alluratest/validation.py b/AlluraTest/alluratest/validation.py
index 2ad3821..8e94b14 100644
--- a/AlluraTest/alluratest/validation.py
+++ b/AlluraTest/alluratest/validation.py
@@ -29,7 +29,7 @@ import logging
 import tempfile
 import subprocess
 import json
-import urllib2
+import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
 import re
 import pkg_resources
 import six
@@ -64,8 +64,8 @@ class Config(object):
     def test_ini(self):
         if not self.ini_config:
             from . import controller
-            import ConfigParser
-            conf = ConfigParser.ConfigParser(
+            import six.moves.configparser
+            conf = six.moves.configparser.ConfigParser(
                 {'validate_html5': 'false', 'validate_inlinejs': 'false'})
             conf.read(controller.get_config_file())
             self.ini_config = conf
diff --git a/ForgeBlog/forgeblog/main.py b/ForgeBlog/forgeblog/main.py
index 79716af..56488b5 100644
--- a/ForgeBlog/forgeblog/main.py
+++ b/ForgeBlog/forgeblog/main.py
@@ -19,7 +19,7 @@
 from __future__ import unicode_literals
 from __future__ import absolute_import
 import logging
-import urllib2
+import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
 import json
 
 # Non-stdlib imports
@@ -332,7 +332,7 @@ class RootController(BaseController, FeedController):
     def _lookup(self, year=None, month=None, name=None, *rest):
         if year is None or month is None or name is None:
             raise exc.HTTPNotFound()
-        slug = '/'.join((year, month, urllib2.unquote(name).decode('utf-8')))
+        slug = '/'.join((year, month, six.moves.urllib.parse.unquote(name).decode('utf-8')))
         post = BM.BlogPost.query.get(slug=slug, app_config_id=c.app.config._id)
         if post is None:
             raise exc.HTTPNotFound()
@@ -610,7 +610,7 @@ class RootRestController(BaseController, AppRestControllerMixin):
     def _lookup(self, year=None, month=None, title=None, *rest):
         if not (year and month and title):
             raise exc.HTTPNotFound()
-        slug = '/'.join((year, month, urllib2.unquote(title).decode('utf-8')))
+        slug = '/'.join((year, month, six.moves.urllib.parse.unquote(title).decode('utf-8')))
         post = BM.BlogPost.query.get(slug=slug, app_config_id=c.app.config._id)
         if not post:
             raise exc.HTTPNotFound()
diff --git a/ForgeChat/forgechat/command.py b/ForgeChat/forgechat/command.py
index a1a0806..6c9c0c8 100644
--- a/ForgeChat/forgechat/command.py
+++ b/ForgeChat/forgechat/command.py
@@ -23,7 +23,7 @@ import socket
 import asyncore
 import asynchat
 import random
-from urlparse import urljoin
+from six.moves.urllib.parse import urljoin
 from datetime import datetime, timedelta
 
 import tg
diff --git a/ForgeDiscussion/forgediscussion/controllers/root.py b/ForgeDiscussion/forgediscussion/controllers/root.py
index 5653b76..1e2e6a4 100644
--- a/ForgeDiscussion/forgediscussion/controllers/root.py
+++ b/ForgeDiscussion/forgediscussion/controllers/root.py
@@ -19,7 +19,7 @@ from __future__ import unicode_literals
 from __future__ import absolute_import
 import json
 import logging
-from urllib import unquote
+from six.moves.urllib.parse import unquote
 from datetime import date, datetime, timedelta, time
 import calendar
 from collections import OrderedDict
diff --git a/ForgeDiscussion/forgediscussion/forum_main.py b/ForgeDiscussion/forgediscussion/forum_main.py
index a1ccdab..e481c23 100644
--- a/ForgeDiscussion/forgediscussion/forum_main.py
+++ b/ForgeDiscussion/forgediscussion/forum_main.py
@@ -19,7 +19,7 @@
 from __future__ import unicode_literals
 from __future__ import absolute_import
 import logging
-import urllib
+import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
 import json
 import os
 
@@ -103,7 +103,7 @@ class ForgeDiscussionApp(Application):
         log.info('Message from %s (%s)',
                  topic, self.config.options.mount_point)
         log.info('Headers are: %s', message['headers'])
-        shortname = urllib.unquote_plus(topic.replace('.', '/'))
+        shortname = six.moves.urllib.parse.unquote_plus(topic.replace('.', '/'))
         forum = DM.Forum.query.get(
             shortname=shortname, app_config_id=self.config._id)
         if forum is None:
diff --git a/ForgeFeedback/forgefeedback/model/feedback.py b/ForgeFeedback/forgefeedback/model/feedback.py
index 28b4948..3285308 100755
--- a/ForgeFeedback/forgefeedback/model/feedback.py
+++ b/ForgeFeedback/forgefeedback/model/feedback.py
@@ -18,7 +18,7 @@
 from __future__ import unicode_literals
 from __future__ import absolute_import
 import logging
-import urllib
+import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
 # Non-stdlib imports
 
 from datetime import datetime
diff --git a/ForgeImporters/forgeimporters/base.py b/ForgeImporters/forgeimporters/base.py
index 1fd5d29..deb96ed 100644
--- a/ForgeImporters/forgeimporters/base.py
+++ b/ForgeImporters/forgeimporters/base.py
@@ -20,11 +20,11 @@ from __future__ import absolute_import
 import os
 import errno
 import logging
-import urllib
-import urllib2
+import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
+import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
 from collections import defaultdict
 import traceback
-from urlparse import urlparse
+from six.moves.urllib.parse import urlparse
 from datetime import datetime
 try:
     from cStringIO import StringIO
@@ -169,7 +169,7 @@ class ProjectExtractor(object):
 
     @staticmethod
     def urlopen(url, retries=3, codes=(408, 500, 502, 503, 504), timeout=120, **kw):
-        req = urllib2.Request(url, **kw)
+        req = six.moves.urllib.request.Request(url, **kw)
         req.add_header(
             'User-Agent', 'Allura Data Importer (https://allura.apache.org/)')
         return h.urlopen(req, retries=retries, codes=codes, timeout=timeout)
@@ -209,7 +209,7 @@ class ProjectExtractor(object):
 
         """
         return self.PAGE_MAP[page_name].format(
-            project_name=urllib.quote(self.project_name), **kw)
+            project_name=six.moves.urllib.parse.quote(self.project_name), **kw)
 
     def parse_page(self, page):
         """Transforms the result of a `urlopen` call before returning it from
diff --git a/ForgeImporters/forgeimporters/github/__init__.py b/ForgeImporters/forgeimporters/github/__init__.py
index c991127..1b67d0a 100644
--- a/ForgeImporters/forgeimporters/github/__init__.py
+++ b/ForgeImporters/forgeimporters/github/__init__.py
@@ -21,7 +21,7 @@ import re
 import logging
 import json
 import time
-import urllib2
+import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
 from datetime import datetime
 
 from tg import config, session, redirect, request, expose
@@ -93,7 +93,7 @@ class GitHubProjectExtractor(base.ProjectExtractor):
         try:
             resp = super(GitHubProjectExtractor, self).urlopen(
                 self.add_token(url), **kw)
-        except urllib2.HTTPError as e:
+        except six.moves.urllib.error.HTTPError as e:
             # GitHub will return 403 if rate limit exceeded.
             # We're checking for limit on every request below, but we still
             # can get 403 if other import task exceeds the limit before.
diff --git a/ForgeImporters/forgeimporters/github/tracker.py b/ForgeImporters/forgeimporters/github/tracker.py
index 1153eb1..7db14e5 100644
--- a/ForgeImporters/forgeimporters/github/tracker.py
+++ b/ForgeImporters/forgeimporters/github/tracker.py
@@ -20,7 +20,7 @@ from __future__ import absolute_import
 import re
 import logging
 from datetime import datetime
-from urllib2 import HTTPError
+from six.moves.urllib.error import HTTPError
 import six
 
 try:
diff --git a/ForgeImporters/forgeimporters/tests/github/test_extractor.py b/ForgeImporters/forgeimporters/tests/github/test_extractor.py
index ca5cd3b..52167c3 100644
--- a/ForgeImporters/forgeimporters/tests/github/test_extractor.py
+++ b/ForgeImporters/forgeimporters/tests/github/test_extractor.py
@@ -19,7 +19,7 @@ from __future__ import unicode_literals
 from __future__ import absolute_import
 import json
 from unittest import TestCase
-import urllib2
+import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
 
 from mock import patch, Mock
 
@@ -204,7 +204,7 @@ class TestGitHubProjectExtractor(TestCase):
             mock_resp = StringIO('{}')
             mock_resp.info = lambda: {}
             urlopen.side_effect = [mock_resp]
-            raise urllib2.HTTPError(
+            raise six.moves.urllib.error.HTTPError(
                 'url', 403, 'msg', limit_exceeded_headers, StringIO('{}'))
         urlopen.side_effect = urlopen_side_effect
         e = github.GitHubProjectExtractor('test_project')
diff --git a/ForgeImporters/forgeimporters/tests/github/test_tracker.py b/ForgeImporters/forgeimporters/tests/github/test_tracker.py
index 87cf96e..83da436 100644
--- a/ForgeImporters/forgeimporters/tests/github/test_tracker.py
+++ b/ForgeImporters/forgeimporters/tests/github/test_tracker.py
@@ -19,7 +19,7 @@ from __future__ import unicode_literals
 from __future__ import absolute_import
 from datetime import datetime
 from unittest import TestCase
-from urllib2 import HTTPError
+from six.moves.urllib.error import HTTPError
 import mock
 
 from ...github import tracker
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index c9aaf8e..d10de45 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -18,7 +18,7 @@
 from __future__ import unicode_literals
 from __future__ import absolute_import
 import logging
-import urllib
+import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
 import json
 import difflib
 from datetime import datetime, timedelta
@@ -604,7 +604,7 @@ class Bin(Artifact, ActivityObject):
         params = dict(q=(h.really_unicode(self.terms).encode('utf-8') or ''))
         if self.sort:
             params['sort'] = self.sort
-        return base + urllib.urlencode(params)
+        return base + six.moves.urllib.parse.urlencode(params)
 
     def shorthand_id(self):
         return self.summary
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index c9770d3..7d5b710 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -19,7 +19,7 @@
 from __future__ import unicode_literals
 from __future__ import absolute_import
 from datetime import datetime
-import urllib
+import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
 import os
 import time
 import json
diff --git a/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py b/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py
index d4492b5..68d10d4 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py
@@ -19,7 +19,7 @@ from __future__ import unicode_literals
 from __future__ import absolute_import
 from tg import tmpl_context as c
 from datetime import datetime
-import urllib2
+import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
 
 import mock
 from ming.orm.ormsession import ThreadLocalORMSession
@@ -319,7 +319,7 @@ class TestTicketModel(TrackerTestWithModel):
             ticket.summary = 'test ticket'
             ticket.description = 'test description'
         assert_equal(len(ticket.attachments), 0)
-        f = urllib2.urlopen('file://%s' % __file__)
+        f = six.moves.urllib.request.urlopen('file://%s' % __file__)
         TicketAttachment.save_attachment(
             'test_ticket_model.py', ResettableStream(f),
             artifact_id=ticket._id)
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index b95c94e..42516c7 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -21,7 +21,7 @@ import logging
 import re
 from datetime import datetime, timedelta
 from functools import partial
-from urllib import urlencode, unquote
+from six.moves.urllib.parse import urlencode, unquote
 from webob import exc
 import json
 import os
diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index 292f055..0c4f0de 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -22,7 +22,7 @@ import json
 import logging
 import os
 from pprint import pformat
-from urllib import unquote
+from six.moves.urllib.parse import unquote
 
 # Non-stdlib imports
 from tg import expose, validate, redirect, flash, jsonify
diff --git a/fuse/accessfs.py b/fuse/accessfs.py
index 9f9805b..a319544 100644
--- a/fuse/accessfs.py
+++ b/fuse/accessfs.py
@@ -22,8 +22,8 @@ from __future__ import print_function
 from __future__ import absolute_import
 import os
 import json
-import urllib
-import urllib2
+import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
+import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
 import sys
 import pwd
 import errno
@@ -338,11 +338,11 @@ class PermissionCache(object):
         url = (
             self._host
             + '/auth/repo_permissions?'
-            + urllib.urlencode(dict(
+            + six.moves.urllib.parse.urlencode(dict(
                 repo_path=path,
                 username=uname)))
         print('Checking access for %s at %s (%s)' % (uname, url, path))
-        fp = urllib2.urlopen(url)
+        fp = six.moves.urllib.request.urlopen(url)
         result = json.load(fp)
         print(result)
         entry = 0
diff --git a/scripts/teamforge-import.py b/scripts/teamforge-import.py
index 4e875bf..7d001c6 100644
--- a/scripts/teamforge-import.py
+++ b/scripts/teamforge-import.py
@@ -27,12 +27,12 @@ import os
 from time import mktime
 import time
 import json
-from urlparse import urlparse
-import urllib2
-import urllib
-from cookielib import CookieJar
+from six.moves.urllib.parse import urlparse
+import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
+import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
+from six.moves.http_cookiejar import CookieJar
 from datetime import datetime
-from ConfigParser import ConfigParser
+from six.moves.configparser import ConfigParser
 import random
 import string
 
@@ -62,7 +62,7 @@ client = None  # main api client
 users = {}
 
 cj = CookieJar()
-loggedInOpener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
+loggedInOpener = six.moves.urllib.request.build_opener(six.moves.urllib.request.HTTPCookieProcessor(cj))
 
 
 def make_client(api_url, app):
@@ -701,7 +701,7 @@ def download_file(tool, url_path, *filepaths):
     else:
         hostname = urlparse(options.api_url).hostname
         scheme = urlparse(options.api_url).scheme
-        url = scheme + '://' + hostname + action_url + urllib.quote(url_path)
+        url = scheme + '://' + hostname + action_url + six.moves.urllib.parse.quote(url_path)
     log.debug('fetching %s' % url)
 
     resp = loggedInOpener.open(url)
@@ -709,7 +709,7 @@ def download_file(tool, url_path, *filepaths):
     # log in to make sure the file should really be html
     if resp.headers.type == 'text/html':
         # log in and save the file
-        resp = loggedInOpener.open(scheme + '://' + hostname + "/sf/sfmain/do/login", urllib.urlencode({
+        resp = loggedInOpener.open(scheme + '://' + hostname + "/sf/sfmain/do/login", six.moves.urllib.parse.urlencode({
             'username': options.username,
             'password': options.password,
             'returnToUrl': url,
diff --git a/scripts/wiki-copy.py b/scripts/wiki-copy.py
index 6f427b6..6182d68 100644
--- a/scripts/wiki-copy.py
+++ b/scripts/wiki-copy.py
@@ -22,12 +22,12 @@ from __future__ import print_function
 from __future__ import absolute_import
 import os
 import sys
-import urllib
-import urlparse
+import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
+import six.moves.urllib.parse
 from optparse import OptionParser
 import json
 
-from ConfigParser import ConfigParser, NoOptionError
+from six.moves.configparser import ConfigParser, NoOptionError
 import webbrowser
 import oauth2 as oauth
 
@@ -46,19 +46,19 @@ def main():
     base_url = options.to_wiki.split('/rest/')[0]
     oauth_client = make_oauth_client(base_url)
 
-    wiki_data = urllib.urlopen(options.from_wiki).read()
+    wiki_data = six.moves.urllib.request.urlopen(options.from_wiki).read()
     wiki_json = json.loads(wiki_data)['pages']
     for p in wiki_json:
-        from_url = options.from_wiki + urllib.quote(p)
-        to_url = options.to_wiki + urllib.quote(p)
+        from_url = options.from_wiki + six.moves.urllib.parse.quote(p)
+        to_url = options.to_wiki + six.moves.urllib.parse.quote(p)
         try:
-            page_data = urllib.urlopen(from_url).read()
+            page_data = six.moves.urllib.request.urlopen(from_url).read()
             page_json = json.loads(page_data)
             if options.debug:
                 print(page_json['text'])
                 break
             resp = oauth_client.request(
-                to_url, 'POST', body=urllib.urlencode(dict(text=page_json['text'].encode('utf-8'))))
+                to_url, 'POST', body=six.moves.urllib.parse.urlencode(dict(text=page_json['text'].encode('utf-8'))))
             if resp[0]['status'] == '200':
                 print("Posted {0} to {1}".format(page_json['title'], to_url))
             else:
@@ -94,7 +94,7 @@ def make_oauth_client(base_url):
         resp, content = client.request(REQUEST_TOKEN_URL, 'GET')
         assert resp['status'] == '200', resp
 
-        request_token = dict(urlparse.parse_qsl(content))
+        request_token = dict(six.moves.urllib.parse.parse_qsl(content))
         pin_url = "%s?oauth_token=%s" % (
             AUTHORIZE_URL, request_token['oauth_token'])
         if getattr(webbrowser.get(), 'name', '') == 'links':
@@ -109,7 +109,7 @@ def make_oauth_client(base_url):
         token.set_verifier(oauth_verifier)
         client = oauth.Client(consumer, token)
         resp, content = client.request(ACCESS_TOKEN_URL, "GET")
-        access_token = dict(urlparse.parse_qsl(content))
+        access_token = dict(six.moves.urllib.parse.parse_qsl(content))
         oauth_token = access_token['oauth_token']
         oauth_token_secret = access_token['oauth_token_secret']