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/01/21 16:03:24 UTC

[allura] 02/12: [#7878] run: python-modernize --future-unicode -n -w --no-diffs -f unicode_future .

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

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

commit 4e8c766f5e1c43fbaa21e535d58707c1ed31d73b
Author: Dave Brondsema <db...@slashdotmedia.com>
AuthorDate: Thu Jan 16 18:08:23 2020 +0000

    [#7878] run: python-modernize --future-unicode -n -w --no-diffs -f unicode_future .
---
 Allura/allura/__init__.py                          |   1 +
 Allura/allura/app.py                               |   5 +-
 Allura/allura/command/__init__.py                  |   1 +
 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                     |   1 +
 Allura/allura/command/taskd_cleanup.py             |   1 +
 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/__init__.py              |   1 +
 Allura/allura/controllers/attachments.py           |   1 +
 Allura/allura/controllers/auth.py                  |  11 +-
 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               |   3 +-
 Allura/allura/controllers/repository.py            |   7 +-
 Allura/allura/controllers/rest.py                  |   1 +
 Allura/allura/controllers/root.py                  |   1 +
 Allura/allura/controllers/search.py                |   1 +
 Allura/allura/controllers/site_admin.py            |  23 +--
 Allura/allura/controllers/static.py                |   1 +
 Allura/allura/controllers/task.py                  |   1 +
 Allura/allura/controllers/trovecategories.py       |   7 +-
 Allura/allura/eventslistener.py                    |   1 +
 Allura/allura/ext/admin/admin_main.py              |   5 +-
 Allura/allura/ext/admin/widgets.py                 |   1 +
 .../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                   |  17 +-
 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                       |   5 +-
 Allura/allura/lib/import_api.py                    |   1 +
 Allura/allura/lib/macro.py                         |   3 +-
 Allura/allura/lib/mail_util.py                     |   7 +-
 Allura/allura/lib/markdown_extensions.py           |   3 +-
 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                        |  27 ++--
 Allura/allura/lib/repository.py                    |   1 +
 Allura/allura/lib/search.py                        |   7 +-
 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                         |   3 +-
 Allura/allura/lib/validators.py                    |   1 +
 Allura/allura/lib/widgets/__init__.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                 |   5 +-
 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                    |   9 +-
 Allura/allura/model/attachments.py                 |   1 +
 Allura/allura/model/auth.py                        |  17 +-
 Allura/allura/model/discuss.py                     |   5 +-
 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                     |   7 +-
 Allura/allura/model/repo.py                        |   1 +
 Allura/allura/model/repo_refresh.py                |   9 +-
 Allura/allura/model/repository.py                  |  11 +-
 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                     |   3 +-
 Allura/allura/scripts/create_sitemap_files.py      |   1 +
 Allura/allura/scripts/delete_projects.py           |   3 +-
 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/export_tasks.py                |   3 +-
 Allura/allura/tasks/index_tasks.py                 |   1 +
 Allura/allura/tasks/mail_tasks.py                  |   3 +-
 Allura/allura/tasks/notification_tasks.py          |   1 +
 Allura/allura/tasks/repo_tasks.py                  |   1 +
 Allura/allura/templates/__init__.py                |   2 +
 .../templates_responsive/responsive_overrides.py   |   1 +
 Allura/allura/tests/__init__.py                    |   1 +
 Allura/allura/tests/decorators.py                  |   1 +
 Allura/allura/tests/functional/__init__.py         |   2 +
 Allura/allura/tests/functional/test_admin.py       | 109 ++++++-------
 Allura/allura/tests/functional/test_auth.py        |   9 +-
 Allura/allura/tests/functional/test_discuss.py     |   1 +
 Allura/allura/tests/functional/test_feeds.py       |   3 +-
 Allura/allura/tests/functional/test_gravatar.py    |   3 +-
 Allura/allura/tests/functional/test_home.py        |  11 +-
 Allura/allura/tests/functional/test_nav.py         |   1 +
 .../allura/tests/functional/test_neighborhood.py   |   9 +-
 .../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  |  39 ++---
 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/tests/functional/test_trovecategory.py  |   1 +
 .../allura/tests/functional/test_user_profile.py   |  13 +-
 Allura/allura/tests/model/__init__.py              |   2 +
 Allura/allura/tests/model/test_artifact.py         |   1 +
 Allura/allura/tests/model/test_auth.py             |   1 +
 Allura/allura/tests/model/test_discussion.py       |   9 +-
 Allura/allura/tests/model/test_filesystem.py       |  11 +-
 Allura/allura/tests/model/test_monq.py             |   1 +
 Allura/allura/tests/model/test_neighborhood.py     |  11 +-
 Allura/allura/tests/model/test_notification.py     |   1 +
 Allura/allura/tests/model/test_oauth.py            |   1 +
 Allura/allura/tests/model/test_project.py          |   5 +-
 Allura/allura/tests/model/test_repo.py             |   5 +-
 Allura/allura/tests/model/test_timeline.py         |   1 +
 .../tests/scripts/test_create_sitemap_files.py     |   1 +
 .../allura/tests/scripts/test_delete_projects.py   |   5 +-
 Allura/allura/tests/scripts/test_reindexes.py      |   1 +
 .../tests/templates/jinja_master/test_lib.py       |   1 +
 Allura/allura/tests/test_app.py                    |   3 +-
 Allura/allura/tests/test_commands.py               |   1 +
 Allura/allura/tests/test_decorators.py             |   1 +
 Allura/allura/tests/test_diff.py                   |   3 +-
 Allura/allura/tests/test_dispatch.py               |   1 +
 Allura/allura/tests/test_globals.py                |  91 +++++------
 Allura/allura/tests/test_helpers.py                |  39 ++---
 Allura/allura/tests/test_mail_util.py              |  35 ++--
 Allura/allura/tests/test_markdown.py               |   1 +
 Allura/allura/tests/test_middlewares.py            |   1 +
 Allura/allura/tests/test_multifactor.py            |   3 +-
 Allura/allura/tests/test_patches.py                |   1 +
 Allura/allura/tests/test_plugin.py                 |  15 +-
 Allura/allura/tests/test_scripttask.py             |   1 +
 Allura/allura/tests/test_security.py               |   1 +
 Allura/allura/tests/test_tasks.py                  |  71 +++++----
 Allura/allura/tests/test_utils.py                  |  15 +-
 Allura/allura/tests/test_validators.py             |   1 +
 Allura/allura/tests/test_webhooks.py               | 111 ++++++-------
 Allura/allura/tests/tscript.py                     |   1 +
 Allura/allura/tests/tscript_error.py               |   1 +
 Allura/allura/tests/unit/controllers/test_auth.py  |   1 +
 .../test_discussion_moderation_controller.py       |   1 +
 .../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/tests/unit/phone/test_phone_service.py  |   1 +
 Allura/allura/tests/unit/spam/test_akismet.py      |  15 +-
 Allura/allura/tests/unit/spam/test_spam_filter.py  |   1 +
 .../allura/tests/unit/spam/test_stopforumspam.py   |   3 +-
 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 +
 .../tests/unit/test_helpers/test_set_context.py    |   1 +
 .../allura/tests/unit/test_ldap_auth_provider.py   |  11 +-
 Allura/allura/tests/unit/test_mixins.py            |   1 +
 .../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           |  19 +--
 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/version.py                           |   1 +
 Allura/allura/webhooks.py                          |  11 +-
 Allura/allura/websetup/__init__.py                 |   1 +
 Allura/allura/websetup/bootstrap.py                |   1 +
 Allura/allura/websetup/schema.py                   |   1 +
 Allura/docs/conf.py                                |   5 +-
 Allura/ldap-setup.py                               |   1 +
 Allura/ldap-userconfig.py                          |   1 +
 Allura/setup.py                                    |   1 +
 AlluraTest/alluratest/controller.py                |   3 +-
 AlluraTest/alluratest/pylint_checkers.py           |   1 +
 AlluraTest/alluratest/smtp_debug.py                |   1 +
 AlluraTest/alluratest/test_syntax.py               |   1 +
 AlluraTest/alluratest/validation.py                |   3 +-
 AlluraTest/setup.py                                |   1 +
 ForgeActivity/forgeactivity/config/resources.py    |   1 +
 ForgeActivity/forgeactivity/main.py                |   5 +-
 .../forgeactivity/tests/functional/test_rest.py    |   1 +
 .../forgeactivity/tests/functional/test_root.py    |   1 +
 ForgeActivity/forgeactivity/widgets/follow.py      |   3 +-
 ForgeActivity/setup.py                             |   1 +
 ForgeBlog/forgeblog/command/base.py                |   1 +
 ForgeBlog/forgeblog/command/rssfeeds.py            |   5 +-
 ForgeBlog/forgeblog/main.py                        |   5 +-
 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         |  11 +-
 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/version.py                     |   1 +
 ForgeBlog/forgeblog/widgets.py                     |   1 +
 ForgeBlog/setup.py                                 |   1 +
 ForgeChat/forgechat/command.py                     |   1 +
 ForgeChat/forgechat/main.py                        |   1 +
 ForgeChat/forgechat/model/chat.py                  |   1 +
 ForgeChat/forgechat/tests/functional/test_root.py  |   1 +
 ForgeChat/forgechat/version.py                     |   1 +
 ForgeChat/setup.py                                 |   1 +
 .../forgediscussion/controllers/forum.py           |   1 +
 .../forgediscussion/controllers/root.py            |   1 +
 ForgeDiscussion/forgediscussion/forum_main.py      |   1 +
 ForgeDiscussion/forgediscussion/import_support.py  |   1 +
 ForgeDiscussion/forgediscussion/model/forum.py     |   1 +
 ForgeDiscussion/forgediscussion/site_stats.py      |   1 +
 ForgeDiscussion/forgediscussion/tasks.py           |   1 +
 .../forgediscussion/tests/functional/test_forum.py |  19 +--
 .../tests/functional/test_forum_admin.py           |   1 +
 .../tests/functional/test_import.py                |   1 +
 .../forgediscussion/tests/functional/test_rest.py  |  11 +-
 ForgeDiscussion/forgediscussion/tests/test_app.py  |  21 +--
 .../forgediscussion/tests/test_forum_roles.py      |   1 +
 ForgeDiscussion/forgediscussion/utils.py           |   1 +
 ForgeDiscussion/forgediscussion/version.py         |   1 +
 .../forgediscussion/widgets/__init__.py            |   1 +
 ForgeDiscussion/forgediscussion/widgets/admin.py   |   3 +-
 .../forgediscussion/widgets/forum_widgets.py       |   1 +
 ForgeDiscussion/setup.py                           |   1 +
 ForgeFeedback/forgefeedback/feedback_main.py       |   1 +
 ForgeFeedback/forgefeedback/model/feedback.py      |   1 +
 .../forgefeedback/tests/functional/test_root.py    |   1 +
 .../forgefeedback/tests/test_feedback_roles.py     |   1 +
 ForgeFeedback/forgefeedback/tests/unit/__init__.py |   1 +
 .../forgefeedback/tests/unit/test_feedback.py      |   1 +
 .../tests/unit/test_root_controller.py             |   1 +
 ForgeFeedback/forgefeedback/version.py             |   1 +
 ForgeFeedback/setup.py                             |   1 +
 ForgeGit/forgegit/controllers.py                   |   1 +
 ForgeGit/forgegit/git_main.py                      |   1 +
 ForgeGit/forgegit/model/git_repo.py                |   5 +-
 ForgeGit/forgegit/tests/__init__.py                |   1 +
 ForgeGit/forgegit/tests/functional/test_auth.py    |   1 +
 .../forgegit/tests/functional/test_controllers.py  |  23 +--
 ForgeGit/forgegit/tests/model/test_repository.py   | 169 ++++++++++----------
 ForgeGit/forgegit/tests/test_git_app.py            |   1 +
 ForgeGit/forgegit/tests/test_tasks.py              |   1 +
 ForgeGit/forgegit/version.py                       |   1 +
 ForgeGit/setup.py                                  |   1 +
 ForgeImporters/docs/conf.py                        |   5 +-
 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/github/tests/test_code.py       |   9 +-
 .../forgeimporters/github/tests/test_oauth.py      |   1 +
 .../forgeimporters/github/tests/test_tracker.py    |   9 +-
 .../forgeimporters/github/tests/test_utils.py      |  17 +-
 .../forgeimporters/github/tests/test_wiki.py       | 177 +++++++++++----------
 ForgeImporters/forgeimporters/github/tracker.py    |  13 +-
 ForgeImporters/forgeimporters/github/utils.py      |   7 +-
 ForgeImporters/forgeimporters/github/wiki.py       |  13 +-
 .../forgeimporters/tests/forge/test_tracker.py     |   5 +-
 .../tests/github/functional/test_github.py         |   1 +
 .../forgeimporters/tests/github/test_extractor.py  |  29 ++--
 .../forgeimporters/tests/github/test_tasks.py      |   1 +
 .../forgeimporters/tests/github/test_tracker.py    |   5 +-
 ForgeImporters/forgeimporters/tests/test_base.py   |   1 +
 ForgeImporters/forgeimporters/trac/__init__.py     |   1 +
 ForgeImporters/forgeimporters/trac/project.py      |   1 +
 .../trac/tests/functional/test_trac.py             |   1 +
 .../forgeimporters/trac/tests/test_tickets.py      |   7 +-
 ForgeImporters/forgeimporters/trac/tickets.py      |   1 +
 ForgeImporters/setup.py                            |   1 +
 ForgeLink/forgelink/link_main.py                   |   1 +
 ForgeLink/forgelink/tests/functional/test_rest.py  |  15 +-
 ForgeLink/forgelink/tests/functional/test_root.py  |   3 +-
 ForgeLink/forgelink/tests/test_app.py              |   1 +
 ForgeLink/forgelink/version.py                     |   1 +
 ForgeLink/setup.py                                 |   1 +
 ForgeSVN/forgesvn/controllers.py                   |   1 +
 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/tests/functional/test_controllers.py  |   5 +-
 ForgeSVN/forgesvn/tests/model/test_repository.py   | 141 ++++++++--------
 .../forgesvn/tests/model/test_svnimplementation.py |   1 +
 ForgeSVN/forgesvn/tests/test_svn_app.py            |   1 +
 ForgeSVN/forgesvn/tests/test_tasks.py              |   1 +
 ForgeSVN/forgesvn/version.py                       |   1 +
 ForgeSVN/forgesvn/widgets.py                       |   1 +
 ForgeSVN/setup.py                                  |   1 +
 ForgeShortUrl/forgeshorturl/main.py                |   1 +
 ForgeShortUrl/forgeshorturl/model/shorturl.py      |   1 +
 .../forgeshorturl/tests/functional/test.py         |   1 +
 ForgeShortUrl/forgeshorturl/widgets/short_url.py   |   1 +
 ForgeShortUrl/setup.py                             |   1 +
 .../forgetracker/command/fix_discussion.py         |   1 +
 ForgeTracker/forgetracker/config/resources.py      |   1 +
 ForgeTracker/forgetracker/import_support.py        |   9 +-
 ForgeTracker/forgetracker/model/ticket.py          |   3 +-
 ForgeTracker/forgetracker/search.py                |   1 +
 ForgeTracker/forgetracker/site_stats.py            |   1 +
 ForgeTracker/forgetracker/tasks.py                 |   1 +
 .../tests/command/test_fix_discussion.py           |   1 +
 .../forgetracker/tests/functional/test_rest.py     |   1 +
 .../forgetracker/tests/functional/test_root.py     |  53 +++---
 ForgeTracker/forgetracker/tests/test_app.py        |   1 +
 .../forgetracker/tests/test_tracker_roles.py       |   1 +
 ForgeTracker/forgetracker/tests/unit/__init__.py   |   1 +
 .../forgetracker/tests/unit/test_globals_model.py  |   1 +
 .../tests/unit/test_milestone_controller.py        |   5 +-
 .../tests/unit/test_root_controller.py             |   1 +
 .../forgetracker/tests/unit/test_search.py         |   1 +
 .../tests/unit/test_ticket_custom_fields_form.py   |   1 +
 .../forgetracker/tests/unit/test_ticket_form.py    |   1 +
 .../forgetracker/tests/unit/test_ticket_model.py   |   1 +
 ForgeTracker/forgetracker/tracker_main.py          |  11 +-
 ForgeTracker/forgetracker/version.py               |   1 +
 ForgeTracker/forgetracker/widgets/admin.py         |   1 +
 .../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/controllers/userstats.py        |   1 +
 ForgeUserStats/forgeuserstats/main.py              |   1 +
 ForgeUserStats/forgeuserstats/model/stats.py       |   1 +
 ForgeUserStats/forgeuserstats/tests/test_model.py  |   1 +
 ForgeUserStats/forgeuserstats/tests/test_stats.py  |   1 +
 ForgeUserStats/forgeuserstats/version.py           |   1 +
 ForgeUserStats/forgeuserstats/widgets/forms.py     |   1 +
 ForgeUserStats/setup.py                            |   1 +
 ForgeWiki/forgewiki/converters.py                  |   1 +
 ForgeWiki/forgewiki/model/wiki.py                  |   1 +
 ForgeWiki/forgewiki/tests/functional/test_rest.py  |  11 +-
 ForgeWiki/forgewiki/tests/functional/test_root.py  |  25 +--
 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/version.py                     |   1 +
 ForgeWiki/forgewiki/wiki_main.py                   |   5 +-
 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 +
 .../015-add-neighborhood_id-to-blog-posts.py       |   1 +
 scripts/migrations/018-add-svn-checkout-url.py     |   1 +
 .../migrations/020-remove-wiki-title-slashes.py    |   1 +
 scripts/migrations/022-change-anon-display-name.py |   1 +
 .../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 +
 .../027-change-ticket-write-permissions.py         |   1 +
 scripts/migrations/028-remove-svn-trees.py         |   1 +
 scripts/migrations/029-set-mailbox-queue_empty.py  |   1 +
 .../migrations/031-set-user-pending-to-false.py    |   1 +
 .../032-subscribe-merge-request-submitters.py      |   1 +
 .../033-change-comment-anon-permissions.py         |   1 +
 ...34-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 +
 420 files changed, 1261 insertions(+), 838 deletions(-)

diff --git a/Allura/allura/__init__.py b/Allura/allura/__init__.py
index 15c3ab2..87deecd 100644
--- a/Allura/allura/__init__.py
+++ b/Allura/allura/__init__.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 """The allura package"""
+from __future__ import unicode_literals
 from tg.support.registry import StackedObjectProxy
 
 credentials = StackedObjectProxy(name='credentials')
diff --git a/Allura/allura/app.py b/Allura/allura/app.py
index b238f67..478b48f 100644
--- a/Allura/allura/app.py
+++ b/Allura/allura/app.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import logging
 from urllib import basejoin
@@ -655,7 +656,7 @@ class Application(object):
     def admin_menu_collapse_button(self):
         """Returns button for showing/hiding admin sidebar menu"""
         return SitemapEntry(
-            label=u'Admin - {}'.format(self.config.options.mount_label),
+            label='Admin - {}'.format(self.config.options.mount_label),
             extra_html_attrs={
                 'id': 'sidebar-admin-menu-trigger',
             })
@@ -960,7 +961,7 @@ class DefaultAdminController(BaseController, AdminControllerMixin):
                 try:
                     val = opt.validate(val)
                 except fev.Invalid as e:
-                    flash(u'{}: {}'.format(opt.name, str(e)), 'error')
+                    flash('{}: {}'.format(opt.name, str(e)), 'error')
                     continue
                 self.app.config.options[opt.name] = val
             if is_admin:
diff --git a/Allura/allura/command/__init__.py b/Allura/allura/command/__init__.py
index 0221b7b..d6d0c92 100644
--- a/Allura/allura/command/__init__.py
+++ b/Allura/allura/command/__init__.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from base import Command
 from show_models import ShowModelsCommand, ReindexCommand, EnsureIndexCommand
 from script import ScriptCommand, SetToolAccessCommand
diff --git a/Allura/allura/command/base.py b/Allura/allura/command/base.py
index 9a7689a..470a509 100644
--- a/Allura/allura/command/base.py
+++ b/Allura/allura/command/base.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import logging
 import shlex
diff --git a/Allura/allura/command/create_neighborhood.py b/Allura/allura/command/create_neighborhood.py
index dc4b2cd..e1dc85a 100644
--- a/Allura/allura/command/create_neighborhood.py
+++ b/Allura/allura/command/create_neighborhood.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 
 from . import base
diff --git a/Allura/allura/command/create_trove_categories.py b/Allura/allura/command/create_trove_categories.py
index 288117c..da28728 100644
--- a/Allura/allura/command/create_trove_categories.py
+++ b/Allura/allura/command/create_trove_categories.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import re
 import sys
 import logging
diff --git a/Allura/allura/command/reclone_repo.py b/Allura/allura/command/reclone_repo.py
index 51e5ca6..abbf9fb 100644
--- a/Allura/allura/command/reclone_repo.py
+++ b/Allura/allura/command/reclone_repo.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import warnings
 
 from tg import tmpl_context as c
diff --git a/Allura/allura/command/script.py b/Allura/allura/command/script.py
index 7bc3b8c..de77136 100644
--- a/Allura/allura/command/script.py
+++ b/Allura/allura/command/script.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 36ba22b..b10f9fd 100644
--- a/Allura/allura/command/set_neighborhood_features.py
+++ b/Allura/allura/command/set_neighborhood_features.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 86180d4..e082f9b 100644
--- a/Allura/allura/command/show_models.py
+++ b/Allura/allura/command/show_models.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 40008d7..4036084 100644
--- a/Allura/allura/command/smtp_server.py
+++ b/Allura/allura/command/smtp_server.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import smtpd
 import asyncore
 
diff --git a/Allura/allura/command/taskd.py b/Allura/allura/command/taskd.py
index d305c74..5eb2559 100644
--- a/Allura/allura/command/taskd.py
+++ b/Allura/allura/command/taskd.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import os
 import time
diff --git a/Allura/allura/command/taskd_cleanup.py b/Allura/allura/command/taskd_cleanup.py
index a796e6c..3ce1421 100644
--- a/Allura/allura/command/taskd_cleanup.py
+++ b/Allura/allura/command/taskd_cleanup.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import time
 import signal
diff --git a/Allura/allura/config/app_cfg.py b/Allura/allura/config/app_cfg.py
index f5b1464..547403b 100644
--- a/Allura/allura/config/app_cfg.py
+++ b/Allura/allura/config/app_cfg.py
@@ -30,6 +30,7 @@ convert them into boolean, for example, you should use the
     setting = asbool(global_conf.get('the_setting'))
 
 """
+from __future__ import unicode_literals
 import logging
 from functools import partial
 
diff --git a/Allura/allura/config/environment.py b/Allura/allura/config/environment.py
index bf0f5b6..e6ea993 100644
--- a/Allura/allura/config/environment.py
+++ b/Allura/allura/config/environment.py
@@ -19,6 +19,7 @@
 
 """WSGI environment setup for allura."""
 
+from __future__ import unicode_literals
 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 6ddd6fc..1834cc6 100644
--- a/Allura/allura/config/middleware.py
+++ b/Allura/allura/config/middleware.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 """WSGI middleware initialization for the allura application."""
+from __future__ import unicode_literals
 import importlib
 import mimetypes
 
diff --git a/Allura/allura/config/resources.py b/Allura/allura/config/resources.py
index e8717fe..cf683d3 100644
--- a/Allura/allura/config/resources.py
+++ b/Allura/allura/config/resources.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import logging
 
diff --git a/Allura/allura/controllers/__init__.py b/Allura/allura/controllers/__init__.py
index 417b8ad..1e5cd2c 100644
--- a/Allura/allura/controllers/__init__.py
+++ b/Allura/allura/controllers/__init__.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 """Controllers for the allura application."""
+from __future__ import unicode_literals
 from .discuss import DiscussionController, AppDiscussionController, ThreadController, PostController
 from .discuss import ModerationController, AppDiscussionRestController
 from .base import BaseController, DispatchIndex
diff --git a/Allura/allura/controllers/attachments.py b/Allura/allura/controllers/attachments.py
index 11bf24d..15419f2 100644
--- a/Allura/allura/controllers/attachments.py
+++ b/Allura/allura/controllers/attachments.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from urllib import unquote
 from webob import exc
 
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 2ca07c7..b6e21c5 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import os
 from datetime import datetime, timedelta
@@ -676,7 +677,7 @@ class PreferencesController(BaseController):
             user=c.user,
             config=config,
         ))
-        send_system_mail_to_user(c.user, u'Password Changed', email_body)
+        send_system_mail_to_user(c.user, 'Password Changed', email_body)
         redirect('.')
 
     @expose()
@@ -775,7 +776,7 @@ class PreferencesController(BaseController):
                 user=c.user,
                 config=config,
             ))
-            send_system_mail_to_user(c.user, u'Two-Factor Authentication Enabled', email_body)
+            send_system_mail_to_user(c.user, 'Two-Factor Authentication Enabled', email_body)
             redirect('/auth/preferences/multifactor_recovery')
 
     @expose()
@@ -797,7 +798,7 @@ class PreferencesController(BaseController):
             user=c.user,
             config=config,
         ))
-        send_system_mail_to_user(c.user, u'Two-Factor Authentication Disabled', email_body)
+        send_system_mail_to_user(c.user, 'Two-Factor Authentication Disabled', email_body)
         redirect('.')
 
     @expose()
@@ -810,7 +811,7 @@ class PreferencesController(BaseController):
             user=c.user,
             config=config,
         ))
-        send_system_mail_to_user(c.user, u'Two-Factor Authentication Apps', email_body)
+        send_system_mail_to_user(c.user, 'Two-Factor Authentication Apps', email_body)
 
     @expose('jinja:allura:templates/user_recovery_codes.html')
     @reconfirm_auth
@@ -850,7 +851,7 @@ class PreferencesController(BaseController):
             config=config,
         ))
         h.auditlog_user('Regenerated multifactor recovery codes')
-        send_system_mail_to_user(c.user, u'Two-Factor Recovery Codes Regenerated', email_body)
+        send_system_mail_to_user(c.user, 'Two-Factor Recovery Codes Regenerated', email_body)
         tg.flash('Your recovery codes have been regenerated.  Save the new codes!')
         redirect('/auth/preferences/multifactor_recovery')
 
diff --git a/Allura/allura/controllers/base.py b/Allura/allura/controllers/base.py
index ef91a32..902ffa7 100644
--- a/Allura/allura/controllers/base.py
+++ b/Allura/allura/controllers/base.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 12b86c9..acdaf3e 100644
--- a/Allura/allura/controllers/basetest_project_root.py
+++ b/Allura/allura/controllers/basetest_project_root.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 """Main Controller"""
+from __future__ import unicode_literals
 import logging
 from urllib import unquote
 
diff --git a/Allura/allura/controllers/discuss.py b/Allura/allura/controllers/discuss.py
index 69ea86e..0ec6a1a 100644
--- a/Allura/allura/controllers/discuss.py
+++ b/Allura/allura/controllers/discuss.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from urllib import unquote
 from datetime import datetime
 import logging
@@ -563,7 +564,7 @@ class ModerationController(BaseController):
                     posted.approve()
                     g.spam_checker.submit_ham(posted.text, artifact=posted, user=posted.author())
                     posted.thread.post_to_feed(posted)
-        flash(u'{} {}'.format(h.text.plural(count, 'post', 'posts'),
+        flash('{} {}'.format(h.text.plural(count, 'post', 'posts'),
                               'deleted' if delete else 'marked as spam' if spam else 'approved'))
         redirect(request.referer or '/')
 
diff --git a/Allura/allura/controllers/error.py b/Allura/allura/controllers/error.py
index 5cb26d0..599a8eb 100644
--- a/Allura/allura/controllers/error.py
+++ b/Allura/allura/controllers/error.py
@@ -19,6 +19,7 @@
 
 """Error controller"""
 
+from __future__ import unicode_literals
 from tg import request, expose
 
 __all__ = ['ErrorController']
diff --git a/Allura/allura/controllers/feed.py b/Allura/allura/controllers/feed.py
index 9a9c2ae..b426717 100644
--- a/Allura/allura/controllers/feed.py
+++ b/Allura/allura/controllers/feed.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 58c902e..bdbad3c 100644
--- a/Allura/allura/controllers/project.py
+++ b/Allura/allura/controllers/project.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import re
 import logging
 from datetime import datetime, timedelta
@@ -153,7 +154,7 @@ class NeighborhoodController(object):
     def add_project(self, **form_data):
         with h.login_overlay():
             require_access(self.neighborhood, 'register')
-        verify = c.form_errors == {'_the_form': u'phone-verification'}
+        verify = c.form_errors == {'_the_form': 'phone-verification'}
         c.show_phone_verification_overlay = verify
         c.add_project = W.add_project
         form_data.setdefault('tools', W.add_project.default_tools)
diff --git a/Allura/allura/controllers/repository.py b/Allura/allura/controllers/repository.py
index cc05da3..b4d5a33 100644
--- a/Allura/allura/controllers/repository.py
+++ b/Allura/allura/controllers/repository.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import logging
 import difflib
@@ -904,8 +905,8 @@ class FileBrowser(BaseController):
 
         la = list(a)
         lb = list(b)
-        adesc = (u'a' + h.really_unicode(apath)).encode('utf-8')
-        bdesc = (u'b' + h.really_unicode(b.path())).encode('utf-8')
+        adesc = ('a' + h.really_unicode(apath)).encode('utf-8')
+        bdesc = ('b' + h.really_unicode(b.path())).encode('utf-8')
 
         if not fmt:
             fmt = web_session.get('diformat', '')
@@ -916,7 +917,7 @@ class FileBrowser(BaseController):
             if max(a.size, b.size) > asint(tg.config.get('scm.view.max_syntax_highlight_bytes', 500000)):
                 # have to check the original file size, not diff size, because difflib._mdiff inside HtmlSideBySideDiff
                 # can take an extremely long time on large files (and its even a generator)
-                diff = u'<em>File too large for side-by-side view</em>'
+                diff = '<em>File too large for side-by-side view</em>'
             else:
                 hd = HtmlSideBySideDiff()
                 diff = hd.make_table(la, lb, adesc, bdesc)
diff --git a/Allura/allura/controllers/rest.py b/Allura/allura/controllers/rest.py
index 04dac71..8b81d99 100644
--- a/Allura/allura/controllers/rest.py
+++ b/Allura/allura/controllers/rest.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 """REST Controller"""
+from __future__ import unicode_literals
 import logging
 from urllib import unquote
 
diff --git a/Allura/allura/controllers/root.py b/Allura/allura/controllers/root.py
index be3d5bb..9eb4603 100644
--- a/Allura/allura/controllers/root.py
+++ b/Allura/allura/controllers/root.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 """Main Controller"""
+from __future__ import unicode_literals
 import logging
 from string import Template
 
diff --git a/Allura/allura/controllers/search.py b/Allura/allura/controllers/search.py
index 3fe6f8a..3039ba2 100644
--- a/Allura/allura/controllers/search.py
+++ b/Allura/allura/controllers/search.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 aa7e877..6674133 100644
--- a/Allura/allura/controllers/site_admin.py
+++ b/Allura/allura/controllers/site_admin.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import re
 import logging
 from datetime import datetime, timedelta
@@ -359,12 +360,12 @@ class DeleteProjectsController(object):
         return parsed_projects
 
     def format_parsed_projects(self, projects):
-        template = u'{}    # {}'
+        template = '{}    # {}'
         lines = []
         for input, p, error in projects:
-            comment = u'OK: {}'.format(p.url()) if p else error
+            comment = 'OK: {}'.format(p.url()) if p else error
             lines.append(template.format(input, comment))
-        return u'\n'.join(lines)
+        return '\n'.join(lines)
 
     @with_trailing_slash
     @expose('jinja:allura:templates/site_admin_delete_projects.html')
@@ -380,11 +381,11 @@ class DeleteProjectsController(object):
     @validate(validators=delete_form_validators)
     def confirm(self, projects=None, reason=None, disable_users=False, **kw):
         if not projects:
-            flash(u'No projects specified', 'warning')
+            flash('No projects specified', 'warning')
             redirect('.')
         parsed_projects = self.parse_projects(projects)
         projects = self.format_parsed_projects(parsed_projects)
-        edit_link = u'./?projects={}&reason={}&disable_users={}'.format(
+        edit_link = './?projects={}&reason={}&disable_users={}'.format(
             h.urlquoteplus(projects),
             h.urlquoteplus(reason or ''),
             h.urlquoteplus(disable_users))
@@ -400,20 +401,20 @@ class DeleteProjectsController(object):
     @validate(validators=delete_form_validators)
     def really_delete(self, projects=None, reason=None, disable_users=False, **kw):
         if not projects:
-            flash(u'No projects specified', 'warning')
+            flash('No projects specified', 'warning')
             redirect('.')
         projects = self.parse_projects(projects)
         task_params = [p.url().strip('/') for (_, p, _) in projects if p]
         if not task_params:
-            flash(u'Unable to parse at least one project from your input', 'warning')
+            flash('Unable to parse at least one project from your input', 'warning')
             redirect('.')
-        task_params = u' '.join(task_params)
+        task_params = ' '.join(task_params)
         if reason:
-            task_params = u'-r {} {}'.format(pipes.quote(reason), task_params)
+            task_params = '-r {} {}'.format(pipes.quote(reason), task_params)
         if disable_users:
-            task_params = u'--disable-users {}'.format(task_params)
+            task_params = '--disable-users {}'.format(task_params)
         DeleteProjects.post(task_params)
-        flash(u'Delete scheduled', 'ok')
+        flash('Delete scheduled', 'ok')
         redirect('.')
 
 
diff --git a/Allura/allura/controllers/static.py b/Allura/allura/controllers/static.py
index 15b638c..9cddb41 100644
--- a/Allura/allura/controllers/static.py
+++ b/Allura/allura/controllers/static.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from cStringIO import StringIO
 
 from tg import expose
diff --git a/Allura/allura/controllers/task.py b/Allura/allura/controllers/task.py
index e8669d7..f7651f4 100644
--- a/Allura/allura/controllers/task.py
+++ b/Allura/allura/controllers/task.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 
+from __future__ import unicode_literals
 class TaskController(object):
 
     '''WSGI app providing web-like RPC
diff --git a/Allura/allura/controllers/trovecategories.py b/Allura/allura/controllers/trovecategories.py
index 91450fd..81132da 100644
--- a/Allura/allura/controllers/trovecategories.py
+++ b/Allura/allura/controllers/trovecategories.py
@@ -14,6 +14,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 import re
 from collections import OrderedDict
 
@@ -139,7 +140,7 @@ class TroveCategoryController(BaseController):
         if oldcat:
             raise TroveAdminException(
                 ('A category with shortname "%s" already exists (%s).  Try a different, unique shortname' % (shortname, oldcat.fullpath), "error"),
-                u'?categoryname={}&shortname={}'.format(name, shortname),
+                '?categoryname={}&shortname={}'.format(name, shortname),
                 upper
             )
         else:
@@ -170,9 +171,9 @@ class TroveCategoryController(BaseController):
         flash(*flash_args)
 
         if upper:
-            redirect(u'/categories/{}/{}'.format(upper.trove_cat_id, redir_params))
+            redirect('/categories/{}/{}'.format(upper.trove_cat_id, redir_params))
         else:
-            redirect(u'/categories/{}'.format(redir_params))
+            redirect('/categories/{}'.format(redir_params))
 
     @expose()
     @require_post()
diff --git a/Allura/allura/eventslistener.py b/Allura/allura/eventslistener.py
index f9f7431..c4f077c 100644
--- a/Allura/allura/eventslistener.py
+++ b/Allura/allura/eventslistener.py
@@ -21,6 +21,7 @@ overwrite the methods defined here, which will be called when the related
 event happens, so that the statistics for the given entity are updated.'''
 
 
+from __future__ import unicode_literals
 class EventsListener:
 
     def newArtifact(self, art_type, art_datetime, project, user):
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index b7a9ce8..622aafd 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import re
 import os
@@ -628,13 +629,13 @@ class ProjectAdminController(BaseController):
     @expose()
     @require_post()
     def update_mounts(self, subproject=None, tool=None, new=None, page=0, limit=200, **kw):
-        if new and new['ep_name'] == u'subproject':
+        if new and new['ep_name'] == 'subproject':
             new['ep_name'] = ""
         try:
             new_app = self._update_mounts(subproject, tool, new, **kw)
             if new_app:
                 if getattr(new_app, 'tool_label', '') == 'External Link':
-                    flash(u'{} installed successfully.'.format(new_app.tool_label))
+                    flash('{} installed successfully.'.format(new_app.tool_label))
                 else:
                     new_url = new_app.url
                     if callable(new_url):  # subprojects have a method instead of property
diff --git a/Allura/allura/ext/admin/widgets.py b/Allura/allura/ext/admin/widgets.py
index d27f8fa..3666bb8 100644
--- a/Allura/allura/ext/admin/widgets.py
+++ b/Allura/allura/ext/admin/widgets.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 fb83cb7..20fed9d 100644
--- a/Allura/allura/ext/personal_dashboard/dashboard_main.py
+++ b/Allura/allura/ext/personal_dashboard/dashboard_main.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 0710ea6..37cbd2e 100644
--- a/Allura/allura/ext/project_home/project_main.py
+++ b/Allura/allura/ext/project_home/project_main.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 
 import pkg_resources
diff --git a/Allura/allura/ext/search/search_main.py b/Allura/allura/ext/search/search_main.py
index 0c54021..177354b 100644
--- a/Allura/allura/ext/search/search_main.py
+++ b/Allura/allura/ext/search/search_main.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 4a30276..f99b608 100644
--- a/Allura/allura/ext/user_profile/user_main.py
+++ b/Allura/allura/ext/user_profile/user_main.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 
 import pkg_resources
diff --git a/Allura/allura/lib/AsciiDammit.py b/Allura/allura/lib/AsciiDammit.py
index d86c26d..95d27dd 100644
--- a/Allura/allura/lib/AsciiDammit.py
+++ b/Allura/allura/lib/AsciiDammit.py
@@ -17,6 +17,7 @@ the copyright holder hereby grants irrevocably to every recipient
 all rights in this work otherwise reserved under copyright.
 """
 
+from __future__ import unicode_literals
 __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 8770a5c..5f783e4 100644
--- a/Allura/allura/lib/app_globals.py
+++ b/Allura/allura/lib/app_globals.py
@@ -20,6 +20,7 @@
 
 """The application's Globals object"""
 
+from __future__ import unicode_literals
 import logging
 import cgi
 import hashlib
@@ -81,7 +82,7 @@ class ForgeMarkdown(markdown.Markdown):
             # so we return it as a plain text
             log.info('Text is too big. Skipping markdown processing')
             escaped = cgi.escape(h.really_unicode(source))
-            return h.html.literal(u'<pre>%s</pre>' % escaped)
+            return h.html.literal('<pre>%s</pre>' % escaped)
         try:
             return markdown.Markdown.convert(self, source)
         except Exception:
@@ -89,7 +90,7 @@ class ForgeMarkdown(markdown.Markdown):
                      ''.join(traceback.format_stack()), exc_info=True)
             escaped = h.really_unicode(source)
             escaped = cgi.escape(escaped)
-            return h.html.literal(u"""<p><strong>ERROR!</strong> The markdown supplied could not be parsed correctly.
+            return h.html.literal("""<p><strong>ERROR!</strong> The markdown supplied could not be parsed correctly.
             Did you forget to surround a code snippet with "~~~~"?</p><pre>%s</pre>""" % escaped)
 
     def cached_convert(self, artifact, field_name):
@@ -434,7 +435,7 @@ class Globals(object):
             # no highlighting, but we should escape, encode, and wrap it in
             # a <pre>
             text = cgi.escape(text)
-            return h.html.literal(u'<pre>' + text + u'</pre>')
+            return h.html.literal('<pre>' + text + '</pre>')
         else:
             return h.html.literal(pygments.highlight(text, lexer, formatter))
 
@@ -632,7 +633,7 @@ class Icon(object):
 
     def __init__(self, css, title=None):
         self.css = css
-        self.title = title or u''
+        self.title = title or ''
 
     def render(self, show_title=False, extra_css=None, closing_tag=True, tag='a', **kw):
         title = kw.get('title') or self.title
@@ -644,9 +645,9 @@ class Icon(object):
             attrs['href'] = '#'
         attrs.update(kw)
         attrs = ew._Jinja2Widget().j2_attrs(attrs)
-        visible_title = u''
+        visible_title = ''
         if show_title:
-            visible_title = u'&nbsp;{}'.format(Markup.escape(title))
-        closing_tag = u'</{}>'.format(tag) if closing_tag else u''
-        icon = u'<{} {}><i class="{}"></i>{}{}'.format(tag, attrs, self.css, visible_title, closing_tag)
+            visible_title = '&nbsp;{}'.format(Markup.escape(title))
+        closing_tag = '</{}>'.format(tag) if closing_tag else ''
+        icon = '<{} {}><i class="{}"></i>{}{}'.format(tag, attrs, self.css, visible_title, closing_tag)
         return Markup(icon)
diff --git a/Allura/allura/lib/base.py b/Allura/allura/lib/base.py
index 4c7a2d8..5cff792 100644
--- a/Allura/allura/lib/base.py
+++ b/Allura/allura/lib/base.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 """The base Controller API."""
+from __future__ import unicode_literals
 from tg import TGController
 
 __all__ = ['WsgiDispatchController']
diff --git a/Allura/allura/lib/custom_middleware.py b/Allura/allura/lib/custom_middleware.py
index cc87d44..79092fa 100644
--- a/Allura/allura/lib/custom_middleware.py
+++ b/Allura/allura/lib/custom_middleware.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import re
 import logging
diff --git a/Allura/allura/lib/decorators.py b/Allura/allura/lib/decorators.py
index 80c8d63..eed03b7 100644
--- a/Allura/allura/lib/decorators.py
+++ b/Allura/allura/lib/decorators.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import inspect
 import sys
 import json
diff --git a/Allura/allura/lib/diff.py b/Allura/allura/lib/diff.py
index 2691b65..6c54673 100644
--- a/Allura/allura/lib/diff.py
+++ b/Allura/allura/lib/diff.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import difflib
 from allura.lib import helpers as h
 
diff --git a/Allura/allura/lib/exceptions.py b/Allura/allura/lib/exceptions.py
index 32be05d..6b3ba28 100644
--- a/Allura/allura/lib/exceptions.py
+++ b/Allura/allura/lib/exceptions.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import webob.exc
 from formencode import Invalid
 
diff --git a/Allura/allura/lib/gravatar.py b/Allura/allura/lib/gravatar.py
index a0fb1de..b678d14 100644
--- a/Allura/allura/lib/gravatar.py
+++ b/Allura/allura/lib/gravatar.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import re
 import urllib
 import hashlib
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index 1ea60ef..c204aaf 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -16,6 +16,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 import base64
 import sys
 import os
@@ -153,7 +154,7 @@ def make_safe_path_portion(ustr, relaxed=True):
 
 
 def escape_json(data):
-    return json.dumps(data).replace('<', '\u003C')
+    return json.dumps(data).replace('<', '\\u003C')
 
 
 def monkeypatch(*objs):
@@ -179,7 +180,7 @@ def urlquoteplus(url, safe=""):
 
 def _attempt_encodings(s, encodings):
     if s is None:
-        return u''
+        return ''
     for enc in encodings:
         try:
             if enc is None:
diff --git a/Allura/allura/lib/import_api.py b/Allura/allura/lib/import_api.py
index 60754a6..71080ba 100644
--- a/Allura/allura/lib/import_api.py
+++ b/Allura/allura/lib/import_api.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import urllib
 import urllib2
 import urlparse
diff --git a/Allura/allura/lib/macro.py b/Allura/allura/lib/macro.py
index ae467cd..4a2ec43 100644
--- a/Allura/allura/lib/macro.py
+++ b/Allura/allura/lib/macro.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import cgi
 import random
 import shlex
@@ -80,7 +81,7 @@ class parse(object):
                 log.warn('macro error.  Upwards stack is %s',
                          ''.join(traceback.format_stack()),
                          exc_info=True)
-                msg = cgi.escape(u'[[%s]] (%s)' % (s, repr(ex)))
+                msg = cgi.escape('[[%s]] (%s)' % (s, repr(ex)))
                 return '\n<div class="error"><pre><code>%s</code></pre></div>' % msg
         except Exception, ex:
             raise
diff --git a/Allura/allura/lib/mail_util.py b/Allura/allura/lib/mail_util.py
index c6c6aac..7e09526 100644
--- a/Allura/allura/lib/mail_util.py
+++ b/Allura/allura/lib/mail_util.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import re
 import logging
 import smtplib
@@ -264,7 +265,7 @@ class SMTPClient(object):
         message['From'] = AddrHeader(fromaddr)
         message['Reply-To'] = AddrHeader(reply_to)
         message['Subject'] = Header(subject)
-        message['Message-ID'] = Header('<' + message_id + u'>')
+        message['Message-ID'] = Header('<' + message_id + '>')
         message['Date'] = email.utils.formatdate()
         if sender:
             message['Sender'] = AddrHeader(sender)
@@ -274,11 +275,11 @@ class SMTPClient(object):
         if in_reply_to:
             if not isinstance(in_reply_to, basestring):
                 raise TypeError('Only strings are supported now, not lists')
-            message['In-Reply-To'] = Header(u'<%s>' % in_reply_to)
+            message['In-Reply-To'] = Header('<%s>' % in_reply_to)
             if not references:
                 message['References'] = message['In-Reply-To']
         if references:
-            references = [u'<%s>' % r for r in aslist(references)]
+            references = ['<%s>' % r for r in aslist(references)]
             message['References'] = Header(*references)
         content = message.as_string()
         smtp_addrs = map(_parse_smtp_addr, addrs)
diff --git a/Allura/allura/lib/markdown_extensions.py b/Allura/allura/lib/markdown_extensions.py
index f27e7a3..59233fd 100644
--- a/Allura/allura/lib/markdown_extensions.py
+++ b/Allura/allura/lib/markdown_extensions.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import re
 import logging
 from urlparse import urljoin
@@ -271,7 +272,7 @@ class ForgeExtension(markdown.Extension):
 
 class EmojiExtension(markdown.Extension):
 
-    EMOJI_RE = u'(%s[a-zA-Z0-9\+\-_&.ô’Åéãíç()!#*]+%s)' % (':', ':')
+    EMOJI_RE = '(%s[a-zA-Z0-9\+\-_&.ô’Åéãíç()!#*]+%s)' % (':', ':')
 
     def __init__(self, **kwargs):
         markdown.Extension.__init__(self)
diff --git a/Allura/allura/lib/multifactor.py b/Allura/allura/lib/multifactor.py
index ec0249d..adcb0eb 100644
--- a/Allura/allura/lib/multifactor.py
+++ b/Allura/allura/lib/multifactor.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 be28fed..6b6a8c1 100644
--- a/Allura/allura/lib/package_path_loader.py
+++ b/Allura/allura/lib/package_path_loader.py
@@ -122,6 +122,7 @@ The positioners are:
 **TODO:** Support multiple partial themes
 
 """
+from __future__ import unicode_literals
 import pkg_resources
 import os
 
diff --git a/Allura/allura/lib/patches.py b/Allura/allura/lib/patches.py
index 977f5d1..a7a4dcd 100644
--- a/Allura/allura/lib/patches.py
+++ b/Allura/allura/lib/patches.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import re
 
 import webob
diff --git a/Allura/allura/lib/phone/__init__.py b/Allura/allura/lib/phone/__init__.py
index dd46f2f..acb567c 100644
--- a/Allura/allura/lib/phone/__init__.py
+++ b/Allura/allura/lib/phone/__init__.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 
 log = logging.getLogger(__name__)
diff --git a/Allura/allura/lib/phone/nexmo.py b/Allura/allura/lib/phone/nexmo.py
index 9c1eb61..f621da9 100644
--- a/Allura/allura/lib/phone/nexmo.py
+++ b/Allura/allura/lib/phone/nexmo.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 from urlparse import urljoin
 import cgi
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index 33c61c7..904ddca 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -18,6 +18,7 @@
 '''
 Allura plugins for authentication and project registration
 '''
+from __future__ import unicode_literals
 import re
 import os
 import logging
@@ -242,14 +243,14 @@ class AuthenticationProvider(object):
 
             if trusted:
                 # current user must change password
-                h.auditlog_user(u'Successful login with password in HIBP breach database, '
-                                u'from trusted source (reason: {})'.format(trusted), user=user)
+                h.auditlog_user('Successful login with password in HIBP breach database, '
+                                'from trusted source (reason: {})'.format(trusted), user=user)
                 return 'hibp'  # reason
             else:
                 # current user may not continue, must reset password via email
                 h.auditlog_user('Attempted login from untrusted location with password in HIBP breach database',
                                 user=user)
-                user.send_password_reset_email(subject_tmpl=u'Update your {site_name} password')
+                user.send_password_reset_email(subject_tmpl='Update your {site_name} password')
                 raise exc.HTTPBadRequest('To ensure account security, you must reset your password via email.'
                                          '\n'
                                          'Please check your email to continue.')
@@ -519,13 +520,13 @@ class LocalAuthenticationProvider(AuthenticationProvider):
         user.disabled = True
         session(user).flush(user)
         if kw.get('audit', True):
-            h.auditlog_user(u'Account disabled', user=user)
+            h.auditlog_user('Account disabled', user=user)
 
     def enable_user(self, user, **kw):
         user.disabled = False
         session(user).flush(user)
         if kw.get('audit', True):
-            h.auditlog_user(u'Account enabled', user=user)
+            h.auditlog_user('Account enabled', user=user)
 
     def activate_user(self, user, **kw):
         user.pending = False
@@ -1180,7 +1181,7 @@ class ProjectRegistrationProvider(object):
                 log.info('User %s is already disabled', user.username)
                 continue
             provider.disable_user(user, audit=False)
-            msg = u'Account disabled because project {}{} is deleted. Reason: {}'.format(
+            msg = 'Account disabled because project {}{} is deleted. Reason: {}'.format(
                 project.neighborhood.url_prefix,
                 project.shortname,
                 reason)
@@ -1223,29 +1224,29 @@ class ProjectRegistrationProvider(object):
         '''
         from allura.model import Project, Neighborhood
         if url is None:
-            return None, u'Empty url'
+            return None, 'Empty url'
         url = urlparse(url)
         url = [u for u in url.path.split('/') if u]
         if len(url) == 0:
-            return None, u'Empty url'
+            return None, 'Empty url'
         if len(url) == 1:
             q = Project.query.find(dict(shortname=url[0]))
             cnt = q.count()
             if cnt == 0:
-                return None, u'Project not found'
+                return None, 'Project not found'
             if cnt == 1:
                 return q.first(), None
-            return None, u'Too many matches for project: {}'.format(cnt)
-        n = Neighborhood.query.get(url_prefix=u'/{}/'.format(url[0]))
+            return None, 'Too many matches for project: {}'.format(cnt)
+        n = Neighborhood.query.get(url_prefix='/{}/'.format(url[0]))
         if not n:
-            return None, u'Neighborhood not found'
+            return None, 'Neighborhood not found'
         p = Project.query.get(neighborhood_id=n._id, shortname=n.shortname_prefix + url[1])
         if len(url) > 2:
             # Maybe subproject
             subp = Project.query.get(neighborhood_id=n._id, shortname='{}/{}'.format(*url[1:3]))
             if subp:
                 return (subp, None)
-        return (p, u'Project not found' if p is None else None)
+        return (p, 'Project not found' if p is None else None)
 
 
 class ThemeProvider(object):
diff --git a/Allura/allura/lib/repository.py b/Allura/allura/lib/repository.py
index 6250026..f05206c 100644
--- a/Allura/allura/lib/repository.py
+++ b/Allura/allura/lib/repository.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 from urllib import quote
 
diff --git a/Allura/allura/lib/search.py b/Allura/allura/lib/search.py
index fdad56e..887e8c2 100644
--- a/Allura/allura/lib/search.py
+++ b/Allura/allura/lib/search.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import re
 import socket
 from logging import getLogger
@@ -143,7 +144,7 @@ def search(q, short_timeout=False, ignore_errors=True, **kw):
         log.exception('Error in solr search')
         if not ignore_errors:
             match = re.search(r'<pre>(.*)</pre>', six.text_type(e))
-            raise SearchError(u'Error running search query: %s' %
+            raise SearchError('Error running search query: %s' %
                               (match.group(1) if match else e))
 
 
@@ -204,9 +205,9 @@ def site_admin_search(model, q, field, **kw):
         # escaping spaces with '\ ' isn't sufficient for display_name_t since its stored as text_general (why??)
         # and wouldn't handle foo@bar.com split on @ either
         # This should work, but doesn't for unknown reasons: q = u'{!term f=%s}%s' % (field, q)
-        q = obj.translate_query(u'%s:(%s)' % (field, q), fields)
+        q = obj.translate_query('%s:(%s)' % (field, q), fields)
         kw['q.op'] = 'AND'  # so that all terms within the () are required
-    fq = [u'type_s:%s' % model.type_s]
+    fq = ['type_s:%s' % model.type_s]
     return search(q, fq=fq, ignore_errors=False, **kw)
 
 
diff --git a/Allura/allura/lib/solr.py b/Allura/allura/lib/solr.py
index 3df3a6f..307a4ab 100644
--- a/Allura/allura/lib/solr.py
+++ b/Allura/allura/lib/solr.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import shlex
 import logging
 
diff --git a/Allura/allura/lib/spam/__init__.py b/Allura/allura/lib/spam/__init__.py
index b51f20d..793999d 100644
--- a/Allura/allura/lib/spam/__init__.py
+++ b/Allura/allura/lib/spam/__init__.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 from copy import copy
 
diff --git a/Allura/allura/lib/spam/akismetfilter.py b/Allura/allura/lib/spam/akismetfilter.py
index e30f05e..a6e2115 100644
--- a/Allura/allura/lib/spam/akismetfilter.py
+++ b/Allura/allura/lib/spam/akismetfilter.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 
 from tg import request
diff --git a/Allura/allura/lib/spam/stopforumspamfilter.py b/Allura/allura/lib/spam/stopforumspamfilter.py
index 9499fec..b8af127 100644
--- a/Allura/allura/lib/spam/stopforumspamfilter.py
+++ b/Allura/allura/lib/spam/stopforumspamfilter.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import csv
 from sys import getsizeof
diff --git a/Allura/allura/lib/utils.py b/Allura/allura/lib/utils.py
index 2554af3..2e6ea3b 100644
--- a/Allura/allura/lib/utils.py
+++ b/Allura/allura/lib/utils.py
@@ -14,6 +14,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 from contextlib import contextmanager
 import time
 import string
@@ -498,7 +499,7 @@ def serve_file(fp, filename, content_type, last_modified=None,
                cache_expires=None, size=None, embed=True, etag=None):
     '''Sets the response headers and serves as a wsgi iter'''
     if not etag and filename and last_modified:
-        etag = u'{0}?{1}'.format(filename, last_modified).encode('utf-8')
+        etag = '{0}?{1}'.format(filename, last_modified).encode('utf-8')
     if etag:
         etag_cache(etag)
     tg.response.headers['Content-Type'] = ''
diff --git a/Allura/allura/lib/validators.py b/Allura/allura/lib/validators.py
index b130634..7bcbbb4 100644
--- a/Allura/allura/lib/validators.py
+++ b/Allura/allura/lib/validators.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import json
 import re
 from bson import ObjectId
diff --git a/Allura/allura/lib/widgets/__init__.py b/Allura/allura/lib/widgets/__init__.py
index 3e8e798..b08a310 100644
--- a/Allura/allura/lib/widgets/__init__.py
+++ b/Allura/allura/lib/widgets/__init__.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from .discuss import Post, Thread
 from .subscriptions import SubscriptionForm
 from .oauth_widgets import OAuthApplicationForm, OAuthRevocationForm
diff --git a/Allura/allura/lib/widgets/analytics.py b/Allura/allura/lib/widgets/analytics.py
index c2e85c5..08f5cb0 100644
--- a/Allura/allura/lib/widgets/analytics.py
+++ b/Allura/allura/lib/widgets/analytics.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import ew
 
 
diff --git a/Allura/allura/lib/widgets/auth_widgets.py b/Allura/allura/lib/widgets/auth_widgets.py
index 47c6764..28b916a 100644
--- a/Allura/allura/lib/widgets/auth_widgets.py
+++ b/Allura/allura/lib/widgets/auth_widgets.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 5d9be46..703718c 100644
--- a/Allura/allura/lib/widgets/discuss.py
+++ b/Allura/allura/lib/widgets/discuss.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 7a5110a..893f1fa 100644
--- a/Allura/allura/lib/widgets/form_fields.py
+++ b/Allura/allura/lib/widgets/form_fields.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 930b6bc..0c8fc80 100644
--- a/Allura/allura/lib/widgets/forms.py
+++ b/Allura/allura/lib/widgets/forms.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import warnings
 
@@ -970,7 +971,7 @@ class NeighborhoodAddProjectForm(ForgeForm):
         submit_text='Start',
         neighborhood=None)
     # tools installed by default
-    default_tools = [u'wiki', u'git', u'tickets', u'discussion']
+    default_tools = ['wiki', 'git', 'tickets', 'discussion']
 
     @property
     def fields(self):
@@ -1007,7 +1008,7 @@ class NeighborhoodAddProjectForm(ForgeForm):
         value = super(NeighborhoodAddProjectForm, self).validate(value, state)
         provider = plugin.ProjectRegistrationProvider.get()
         if not provider.phone_verified(c.user, c.project.neighborhood):
-            raise formencode.Invalid(u'phone-verification', value, None)
+            raise formencode.Invalid('phone-verification', value, None)
         return value
 
     def resources(self):
diff --git a/Allura/allura/lib/widgets/macros.py b/Allura/allura/lib/widgets/macros.py
index 77c329a..a709ac4 100644
--- a/Allura/allura/lib/widgets/macros.py
+++ b/Allura/allura/lib/widgets/macros.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import ew
 
 
diff --git a/Allura/allura/lib/widgets/oauth_widgets.py b/Allura/allura/lib/widgets/oauth_widgets.py
index f04fed8..b73c92c 100644
--- a/Allura/allura/lib/widgets/oauth_widgets.py
+++ b/Allura/allura/lib/widgets/oauth_widgets.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 ad9d063..ad472f5 100644
--- a/Allura/allura/lib/widgets/project_list.py
+++ b/Allura/allura/lib/widgets/project_list.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 d73ef0c..ecf5b4b 100644
--- a/Allura/allura/lib/widgets/repo.py
+++ b/Allura/allura/lib/widgets/repo.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 b923618..9ed6bf7 100644
--- a/Allura/allura/lib/widgets/search.py
+++ b/Allura/allura/lib/widgets/search.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 83d3037..7b3829b 100644
--- a/Allura/allura/lib/widgets/subscriptions.py
+++ b/Allura/allura/lib/widgets/subscriptions.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 3c51f94..a4089c1 100644
--- a/Allura/allura/lib/widgets/user_profile.py
+++ b/Allura/allura/lib/widgets/user_profile.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import re
 
diff --git a/Allura/allura/lib/widgets/vote.py b/Allura/allura/lib/widgets/vote.py
index 4a8cae9..39ea618 100644
--- a/Allura/allura/lib/widgets/vote.py
+++ b/Allura/allura/lib/widgets/vote.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 b5bbe1b..50bc8e1 100644
--- a/Allura/allura/model/__init__.py
+++ b/Allura/allura/model/__init__.py
@@ -19,6 +19,7 @@
 
 """The application's model objects"""
 
+from __future__ import unicode_literals
 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 873b9e5..89f2159 100644
--- a/Allura/allura/model/artifact.py
+++ b/Allura/allura/model/artifact.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 from collections import defaultdict
 from datetime import datetime
@@ -468,7 +469,7 @@ class Artifact(MappedClass, SearchIndexable):
         False otherwise
         """
         pkg = cls.__module__.split('.', 1)[0]
-        opt = u'{}.rate_limits'.format(pkg)
+        opt = '{}.rate_limits'.format(pkg)
 
         def count_in_app():
             return cls.query.find(dict(app_config_id=app_config._id)).count()
@@ -896,11 +897,11 @@ class Feed(MappedClass):
         self.author_name = ""
         self.author_link = ""
         title_parts = self.title.partition(" modified by ")
-        self.title = u"".join(title_parts[0:2]) + (u"<REDACTED>" if title_parts[2] else '')
+        self.title = "".join(title_parts[0:2]) + ("<REDACTED>" if title_parts[2] else '')
 
     @classmethod
     def from_username(cls, username):
-        return cls.query.find({'author_link': u"/u/{}/".format(username)}).all()
+        return cls.query.find({'author_link': "/u/{}/".format(username)}).all()
 
     @classmethod
     def has_access(cls, artifact):
@@ -960,7 +961,7 @@ class Feed(MappedClass):
              since=None, until=None, page=None, limit=None):
         "Produces webhelper.feedgenerator Feed"
         d = dict(title=title, link=h.absurl(link),
-                 description=description, language=u'en',
+                 description=description, language='en',
                  feed_url=request.url)
         if feed_type == 'atom':
             feed = FG.Atom1Feed(**d)
diff --git a/Allura/allura/model/attachments.py b/Allura/allura/model/attachments.py
index fa67134..ad5549b 100644
--- a/Allura/allura/model/attachments.py
+++ b/Allura/allura/model/attachments.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 356355e..12571a9 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import calendar
 from urlparse import urlparse
@@ -144,7 +145,7 @@ class EmailAddress(MappedClass):
             ))
 
             allura.tasks.mail_tasks.send_system_mail_to_user(self.email,
-                                                             u'%s - Email address claim attempt' % config['site_name'],
+                                                             '%s - Email address claim attempt' % config['site_name'],
                                                              text)
 
     def set_nonce_hash(self):
@@ -168,7 +169,7 @@ please visit the following URL:
             fromaddr=g.noreply,
             reply_to=g.noreply,
             toaddr=self.email,
-            subject=u'%s - Email address verification' % config['site_name'],
+            subject='%s - Email address verification' % config['site_name'],
             message_id=h.gen_message_id(),
             text=text)
 
@@ -300,8 +301,8 @@ class User(MappedClass, ActivityNode, ActivityObject, SearchIndexable):
         session_ua=str))
 
     def __repr__(self):
-        return (u'<User username={s.username!r} display_name={s.display_name!r} _id={s._id!r} '
-                u'disabled={s.disabled!r} pending={s.pending!r}>'.format(s=self))
+        return ('<User username={s.username!r} display_name={s.display_name!r} _id={s._id!r} '
+                'disabled={s.disabled!r} pending={s.pending!r}>'.format(s=self))
 
     def index(self):
         provider = plugin.AuthenticationProvider.get(None)  # no need in request here
@@ -385,7 +386,7 @@ class User(MappedClass, ActivityNode, ActivityObject, SearchIndexable):
             if login_detail:
                 self.add_login_detail(login_detail)
 
-    def send_password_reset_email(self, email_address=None, subject_tmpl=u'{site_name} Password recovery'):
+    def send_password_reset_email(self, email_address=None, subject_tmpl='{site_name} Password recovery'):
         if email_address is None:
             email_address = self.get_pref('email_address')
         reset_url = self.make_password_reset_url()
@@ -787,8 +788,8 @@ class User(MappedClass, ActivityNode, ActivityObject, SearchIndexable):
 
     def email_address_header(self):
         h = header.Header()
-        h.append(u'"%s" ' % self.get_pref('display_name'))
-        h.append(u'<%s>' % self.get_pref('email_address'))
+        h.append('"%s" ' % self.get_pref('display_name'))
+        h.append('<%s>' % self.get_pref('email_address'))
         return h
 
     def update_notifications(self):
@@ -1019,7 +1020,7 @@ class AuditLog(object):
 
     @classmethod
     def comment_user(cls, by, message, *args, **kwargs):
-        message = u'Comment by %s: %s' % (by.username, message)
+        message = 'Comment by %s: %s' % (by.username, message)
         return cls.log_user(message, *args, **kwargs)
 
 
diff --git a/Allura/allura/model/discuss.py b/Allura/allura/model/discuss.py
index 973d196..ed3db2f 100644
--- a/Allura/allura/model/discuss.py
+++ b/Allura/allura/model/discuss.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import logging
 from datetime import datetime
@@ -293,7 +294,7 @@ class Thread(Artifact, ActivityObject):
         roles = [r.name for r in c.project.named_roles]
         spam_check_text = post.text
         if self.include_subject_in_spam_check(post):
-            spam_check_text = self.subject + u'\n' + spam_check_text
+            spam_check_text = self.subject + '\n' + spam_check_text
         spammy = g.spam_checker.check(spam_check_text, artifact=post, user=c.user)
         if c.user in c.project.users_with_role(*roles):
             # always run the check, so it's logged.  But don't act on it for admins/developers of their own project
@@ -772,7 +773,7 @@ class Post(Message, VersionedArtifact, ActivityObject, ReactableArtifact):
             # this means artifact was not auto approved, and all the
             # subscribers did not receive notification. Now, moderator approved
             # artifact/post, so we should re-send actual notification
-            msg_id = u'approved-' + msg_id
+            msg_id = 'approved-' + msg_id
             n = Notification.query.get(_id=msg_id)
             if n:
                 # 'approved' notification also exists, re-send
diff --git a/Allura/allura/model/filesystem.py b/Allura/allura/model/filesystem.py
index 523904c..e1c1bed 100644
--- a/Allura/allura/model/filesystem.py
+++ b/Allura/allura/model/filesystem.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import re
 from cStringIO import StringIO
diff --git a/Allura/allura/model/index.py b/Allura/allura/model/index.py
index 300b9ba..f468608 100644
--- a/Allura/allura/model/index.py
+++ b/Allura/allura/model/index.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 a759c99..97db4e2 100644
--- a/Allura/allura/model/monq_model.py
+++ b/Allura/allura/model/monq_model.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import sys
 import time
 import traceback
diff --git a/Allura/allura/model/multifactor.py b/Allura/allura/model/multifactor.py
index cf88ce6..5f6c6ee 100644
--- a/Allura/allura/model/multifactor.py
+++ b/Allura/allura/model/multifactor.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 
 from ming import schema as S
diff --git a/Allura/allura/model/neighborhood.py b/Allura/allura/model/neighborhood.py
index 38356bf..ac40a13 100644
--- a/Allura/allura/model/neighborhood.py
+++ b/Allura/allura/model/neighborhood.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import re
 import json
 import logging
diff --git a/Allura/allura/model/notification.py b/Allura/allura/model/notification.py
index 1e1a707..4ea53eb 100644
--- a/Allura/allura/model/notification.py
+++ b/Allura/allura/model/notification.py
@@ -34,6 +34,7 @@ Periodically:
 
 '''
 
+from __future__ import unicode_literals
 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 9d93d37..b1d324d 100644
--- a/Allura/allura/model/oauth.py
+++ b/Allura/allura/model/oauth.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 
 import oauth2 as oauth
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index 5a6f896..5d0b2a7 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -16,6 +16,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 from calendar import timegm
 from collections import Counter, OrderedDict
@@ -155,7 +156,7 @@ class TroveCategory(MappedClass):
     @property
     def fullpath_within_type(self):
         'remove first section of full path, and use nicer separator'
-        return u' » '.join(self.fullpath.split(' :: ')[1:])
+        return ' » '.join(self.fullpath.split(' :: ')[1:])
 
     def __json__(self):
         return dict(
@@ -684,7 +685,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
                 if tool_name not in grouped_nav:
                     child = deepcopy(e)
                     # change label to be the tool name (type)
-                    e.label = g.entry_points['tool'][tool_name].tool_label + u' \u25be'
+                    e.label = g.entry_points['tool'][tool_name].tool_label + ' \u25be'
                     # add tool url to list of urls that will match this nav entry
                     # have to do this before changing the url to the list page
                     e.matching_urls.append(e.url)
@@ -782,7 +783,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
         try:
             return opt.validate(value)
         except fe.Invalid as e:
-            raise exceptions.ToolError(u'{}: {}'.format(opt.name, str(e)))
+            raise exceptions.ToolError('{}: {}'.format(opt.name, str(e)))
 
     def last_ordinal_value(self):
         last_menu_item = self.ordered_mounts(include_hidden=True)[-1]
diff --git a/Allura/allura/model/repo.py b/Allura/allura/model/repo.py
index 6231ba4..298fcaf 100644
--- a/Allura/allura/model/repo.py
+++ b/Allura/allura/model/repo.py
@@ -19,6 +19,7 @@
 # For backwards compatibility.
 # These used to be separate in this repo module, now all in repository module
 
+from __future__ import unicode_literals
 from .repository import SUser, SObjType
 from .repository import QSIZE, README_RE, VIEWABLE_EXTENSIONS, PYPELINE_EXTENSIONS, DIFF_SIMILARITY_THRESHOLD
 from .repository import CommitDoc, TreeDoc, LastCommitDoc
diff --git a/Allura/allura/model/repo_refresh.py b/Allura/allura/model/repo_refresh.py
index cf7615a..790cba3 100644
--- a/Allura/allura/model/repo_refresh.py
+++ b/Allura/allura/model/repo_refresh.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 from itertools import chain
 from cPickle import dumps
@@ -105,10 +106,10 @@ def refresh_repo(repo, all_commits=False, notify=True, new_clone=False, commits_
         by_branches, by_tags = _group_commits(repo, commit_ids)
         params = []
         for b, commits in by_branches.iteritems():
-            ref = u'refs/heads/{}'.format(b) if b != '__default__' else None
+            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():
-            ref = u'refs/tags/{}'.format(t)
+            ref = 'refs/tags/{}'.format(t)
             params.append(dict(commit_ids=commits, ref=ref))
         if params:
             RepoPushWebhookSender().send(params)
@@ -236,10 +237,10 @@ def send_notifications(repo, commit_ids):
 
     if commit_msgs:
         if len(commit_msgs) > 1:
-            subject = u"{} new commits to {}".format(len(commit_msgs), repo.app.config.options.mount_label)
+            subject = "{} new commits to {}".format(len(commit_msgs), repo.app.config.options.mount_label)
         else:
             commit = commit_msgs[0]
-            subject = u'New commit {} by {}'.format(commit['shorthand_id'], commit['author'])
+            subject = 'New commit {} by {}'.format(commit['shorthand_id'], commit['author'])
         text = g.jinja2_env.get_template("allura:templates/mail/commits.md").render(
             commit_msgs=commit_msgs,
             max_num_commits=asint(tg.config.get('scm.notify.max_commits', 100)),
diff --git a/Allura/allura/model/repository.py b/Allura/allura/model/repository.py
index 71c1569..512dd68 100644
--- a/Allura/allura/model/repository.py
+++ b/Allura/allura/model/repository.py
@@ -14,6 +14,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 import json
 import os
 import stat
@@ -592,14 +593,14 @@ class Repository(Artifact, ActivityObject):
 
     @property
     def email_address(self):
-        return u'noreply@%s%s' % (self.email_domain, config.common_suffix)
+        return 'noreply@%s%s' % (self.email_domain, config.common_suffix)
 
     def index(self):
         result = Artifact.index(self)
         result.update(
             name_s=self.name,
             type_s=self.type_s,
-            title=u'{} {} repository'.format(self.project.name, self.app.tool_label))
+            title='{} {} repository'.format(self.project.name, self.app.tool_label))
         return result
 
     @property
@@ -892,7 +893,7 @@ class MergeRequest(VersionedArtifact, ActivityObject):
 
     @property
     def email_subject(self):
-        return u'Merge request: ' + self.summary
+        return 'Merge request: ' + self.summary
 
     def merge_allowed(self, user):
         """
@@ -1287,12 +1288,12 @@ class Commit(RepoObject, ActivityObject):
             'author': {
                 'name': self.authored.name,
                 'email': self.authored.email,
-                'username': self.authored_user.username if self.authored_user else u'',
+                'username': self.authored_user.username if self.authored_user else '',
             },
             'committer': {
                 'name': self.committed.name,
                 'email': self.committed.email,
-                'username': self.committed_user.username if self.committed_user else u'',
+                'username': self.committed_user.username if self.committed_user else '',
             },
             'added': self.diffs.added,
             'removed': self.diffs.removed,
diff --git a/Allura/allura/model/session.py b/Allura/allura/model/session.py
index bdd89ac..bff64e9 100644
--- a/Allura/allura/model/session.py
+++ b/Allura/allura/model/session.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import pymongo
 from collections import defaultdict
diff --git a/Allura/allura/model/stats.py b/Allura/allura/model/stats.py
index 0928f51..726f08a 100644
--- a/Allura/allura/model/stats.py
+++ b/Allura/allura/model/stats.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 ee50462..2a1a138 100644
--- a/Allura/allura/model/timeline.py
+++ b/Allura/allura/model/timeline.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import bson
 import logging
 
diff --git a/Allura/allura/model/types.py b/Allura/allura/model/types.py
index 833e685..60bb225 100644
--- a/Allura/allura/model/types.py
+++ b/Allura/allura/model/types.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 96a9ded..b4810d2 100644
--- a/Allura/allura/model/webhook.py
+++ b/Allura/allura/model/webhook.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import datetime as dt
 import json
 
@@ -66,7 +67,7 @@ class Webhook(Artifact):
     def __json__(self):
         return {
             '_id': six.text_type(self._id),
-            'url': h.absurl(u'/rest' + self.url()),
+            'url': h.absurl('/rest' + self.url()),
             'type': six.text_type(self.type),
             'hook_url': six.text_type(self.hook_url),
             'mod_date': self.mod_date,
diff --git a/Allura/allura/scripts/create_sitemap_files.py b/Allura/allura/scripts/create_sitemap_files.py
index 40e4642..2bdbb86 100644
--- a/Allura/allura/scripts/create_sitemap_files.py
+++ b/Allura/allura/scripts/create_sitemap_files.py
@@ -28,6 +28,7 @@ things that would make it faster, if we need/want to.
 2. Use multiprocessing to distribute the offsets to n subprocesses.
 """
 
+from __future__ import unicode_literals
 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 9b28f64..330fe01 100644
--- a/Allura/allura/scripts/delete_projects.py
+++ b/Allura/allura/scripts/delete_projects.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import argparse
 import logging
 
@@ -43,7 +44,7 @@ class DeleteProjects(ScriptTask):
                     user = proj.user_project_of
                     if user:
                         auth_provider.disable_user(user, audit=False)
-                        msg = u'Account disabled because user-project was specified for deletion. Reason: {}'.format(
+                        msg = 'Account disabled because user-project was specified for deletion. Reason: {}'.format(
                             options.reason)
                         log_entry = h.auditlog_user(msg, user=user)
                         session(log_entry).flush(log_entry)
diff --git a/Allura/allura/scripts/disable_users.py b/Allura/allura/scripts/disable_users.py
index 6c6f8b3..63a91a5 100644
--- a/Allura/allura/scripts/disable_users.py
+++ b/Allura/allura/scripts/disable_users.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 84399d8..01e2b8f 100644
--- a/Allura/allura/scripts/refresh_last_commits.py
+++ b/Allura/allura/scripts/refresh_last_commits.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import argparse
 import logging
 from datetime import datetime
diff --git a/Allura/allura/scripts/refreshrepo.py b/Allura/allura/scripts/refreshrepo.py
index 8556f87..e1e9bf9 100644
--- a/Allura/allura/scripts/refreshrepo.py
+++ b/Allura/allura/scripts/refreshrepo.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import argparse
 import logging
 import faulthandler
diff --git a/Allura/allura/scripts/reindex_projects.py b/Allura/allura/scripts/reindex_projects.py
index 37ff222..f14b973 100644
--- a/Allura/allura/scripts/reindex_projects.py
+++ b/Allura/allura/scripts/reindex_projects.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import argparse
 import logging
 
diff --git a/Allura/allura/scripts/reindex_users.py b/Allura/allura/scripts/reindex_users.py
index e2acd3b..427cd09 100644
--- a/Allura/allura/scripts/reindex_users.py
+++ b/Allura/allura/scripts/reindex_users.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import argparse
 import logging
 
diff --git a/Allura/allura/scripts/scripttask.py b/Allura/allura/scripts/scripttask.py
index fb97c2a..ec5e4b2 100644
--- a/Allura/allura/scripts/scripttask.py
+++ b/Allura/allura/scripts/scripttask.py
@@ -44,6 +44,7 @@ To call as a task::
 
 """
 
+from __future__ import unicode_literals
 import argparse
 import logging
 import shlex
diff --git a/Allura/allura/scripts/trac_export.py b/Allura/allura/scripts/trac_export.py
index 5560fd0..d05b68b 100644
--- a/Allura/allura/scripts/trac_export.py
+++ b/Allura/allura/scripts/trac_export.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import sys
 import csv
diff --git a/Allura/allura/tasks/activity_tasks.py b/Allura/allura/tasks/activity_tasks.py
index f6bf8b6..3dc5f77 100644
--- a/Allura/allura/tasks/activity_tasks.py
+++ b/Allura/allura/tasks/activity_tasks.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 7a71444..c3b6c26 100644
--- a/Allura/allura/tasks/admin_tasks.py
+++ b/Allura/allura/tasks/admin_tasks.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import inspect
 
 from tg import tmpl_context as c
diff --git a/Allura/allura/tasks/export_tasks.py b/Allura/allura/tasks/export_tasks.py
index 49771ae..56a19d5 100644
--- a/Allura/allura/tasks/export_tasks.py
+++ b/Allura/allura/tasks/export_tasks.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import os.path
 import logging
@@ -89,7 +90,7 @@ class BulkExport(object):
         }
 
         mail_tasks.send_system_mail_to_user(user,
-                                            u'Bulk export for project %s completed' % project.shortname,
+                                            'Bulk export for project %s completed' % project.shortname,
                                             tmpl.render(tmpl_context))
 
     def filter_exportable(self, apps):
diff --git a/Allura/allura/tasks/index_tasks.py b/Allura/allura/tasks/index_tasks.py
index 631ec14..ef4b80f 100644
--- a/Allura/allura/tasks/index_tasks.py
+++ b/Allura/allura/tasks/index_tasks.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 bab4d69..eaa730e 100644
--- a/Allura/allura/tasks/mail_tasks.py
+++ b/Allura/allura/tasks/mail_tasks.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import HTMLParser
 import re
@@ -262,7 +263,7 @@ def send_system_mail_to_user(user_or_emailaddr, subject, text):
 
     email = {
         'toaddr': toaddr,
-        'fromaddr': u'"{}" <{}>'.format(
+        'fromaddr': '"{}" <{}>'.format(
             config['site_name'],
             config['forgemail.return_path']
         ),
diff --git a/Allura/allura/tasks/notification_tasks.py b/Allura/allura/tasks/notification_tasks.py
index f82063d..c74dd2c 100644
--- a/Allura/allura/tasks/notification_tasks.py
+++ b/Allura/allura/tasks/notification_tasks.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 c84977f..b4fb977 100644
--- a/Allura/allura/tasks/repo_tasks.py
+++ b/Allura/allura/tasks/repo_tasks.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import shutil
 import logging
 import traceback
diff --git a/Allura/allura/templates/__init__.py b/Allura/allura/templates/__init__.py
index 8109045..4ab9cb7 100644
--- a/Allura/allura/templates/__init__.py
+++ b/Allura/allura/templates/__init__.py
@@ -18,3 +18,5 @@
 #       under the License.
 
 """Templates package for the application."""
+
+from __future__ import unicode_literals
\ No newline at end of file
diff --git a/Allura/allura/templates_responsive/responsive_overrides.py b/Allura/allura/templates_responsive/responsive_overrides.py
index 0478620..bcdb910 100644
--- a/Allura/allura/templates_responsive/responsive_overrides.py
+++ b/Allura/allura/templates_responsive/responsive_overrides.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 
+from __future__ import unicode_literals
 class ResponsiveOverrides(object):
     '''
     Placeholder to trigger usage of template overrides in the /override/ dir
diff --git a/Allura/allura/tests/__init__.py b/Allura/allura/tests/__init__.py
index 8047c6b..d557387 100644
--- a/Allura/allura/tests/__init__.py
+++ b/Allura/allura/tests/__init__.py
@@ -19,6 +19,7 @@
 
 """Unit and functional test suite for allura."""
 
+from __future__ import unicode_literals
 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 f044c0e..c1bbcd7 100644
--- a/Allura/allura/tests/decorators.py
+++ b/Allura/allura/tests/decorators.py
@@ -14,6 +14,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 import logging
 import sys
 import re
diff --git a/Allura/allura/tests/functional/__init__.py b/Allura/allura/tests/functional/__init__.py
index 40a4394..9055977 100644
--- a/Allura/allura/tests/functional/__init__.py
+++ b/Allura/allura/tests/functional/__init__.py
@@ -18,3 +18,5 @@
 #       under the License.
 
 """Functional test suite for the controllers of the application."""
+
+from __future__ import unicode_literals
\ No newline at end of file
diff --git a/Allura/allura/tests/functional/test_admin.py b/Allura/allura/tests/functional/test_admin.py
index 534863e..66e6d32 100644
--- a/Allura/allura/tests/functional/test_admin.py
+++ b/Allura/allura/tests/functional/test_admin.py
@@ -16,6 +16,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import allura
 import pkg_resources
@@ -53,12 +54,12 @@ class TestProjectAdmin(TestController):
         with audits(
                 'change summary to Milkshakes are for crazy monkeys',
                 'change project name to My Test Project',
-                u'change short description to (\u00bf A Test Project \?){45}'):
+                'change short description to (\u00bf A Test Project \?){45}'):
             self.app.post('/admin/update', params=dict(
                 name='My Test Project',
                 shortname='test',
                 summary='Milkshakes are for crazy monkeys',
-                short_description=u'\u00bf A Test Project ?'.encode(
+                short_description='\u00bf A Test Project ?'.encode(
                         'utf-8') * 45,
                 labels='aaa,bbb'))
         r = self.app.get('/admin/overview')
@@ -164,7 +165,7 @@ class TestProjectAdmin(TestController):
     def test_features(self):
         proj = M.Project.query.get(shortname='test')
         assert_equals(proj.features, [])
-        with audits(u"change project features to \[u'One', u'Two'\]"):
+        with audits("change project features to \[u'One', u'Two'\]"):
             resp = self.app.post('/admin/update', params={
                 'features-0.feature': 'One',
                 'features-1.feature': '  ',
@@ -181,10 +182,10 @@ class TestProjectAdmin(TestController):
         features = features.findAll('input', {'type': 'text'})
         # two features + extra empty input + stub hidden input for js
         assert_equals(len(features), 2+1+1)
-        assert_equals(features[0]['value'], u'One')
-        assert_equals(features[1]['value'], u'Two')
+        assert_equals(features[0]['value'], 'One')
+        assert_equals(features[1]['value'], 'Two')
         proj = M.Project.query.get(shortname='test')
-        assert_equals(proj.features, [u'One', u'Two'])
+        assert_equals(proj.features, ['One', 'Two'])
 
     @td.with_wiki
     def test_block_user_empty_data(self):
@@ -354,17 +355,17 @@ class TestProjectAdmin(TestController):
 
     def test_install_tool_form(self):
         r = self.app.get('/admin/install_tool?tool_name=wiki')
-        assert_in(u'Installing Wiki', r)
+        assert_in('Installing Wiki', r)
 
     def test_install_tool_form_options(self):
         opts = ['AllowEmailPosting']
         with mock.patch.object(ForgeWikiApp, 'config_on_install', new=opts):
             r = self.app.get('/admin/install_tool?tool_name=wiki')
-            assert_in(u'<input id="AllowEmailPosting" name="AllowEmailPosting"', r)
+            assert_in('<input id="AllowEmailPosting" name="AllowEmailPosting"', r)
 
     def test_install_tool_form_subproject(self):
         r = self.app.get('/admin/install_tool?tool_name=subproject')
-        assert_in(u'Installing Sub Project', r)
+        assert_in('Installing Sub Project', r)
 
     def test_project_icon(self):
         file_name = 'neo-icon-set-454545-256x350.png'
@@ -552,13 +553,13 @@ class TestProjectAdmin(TestController):
             r = form.submit().follow()
         # make sure it worked
         assert 'No Database Environment categories have been selected.' not in r
-        assert u'<span class="trove_fullpath">Database API » Python Database API</span>' in r
+        assert '<span class="trove_fullpath">Database API » Python Database API</span>' in r
         # delete the cat
         with audits('remove trove root_database: Database Environment :: Database API'):
             r = r.forms['delete_trove_root_database_506'].submit().follow()
         # make sure it worked
         assert 'No Database Environment categories have been selected.' in r
-        assert u'<span class="trove_fullpath">Database API » Python Database API</span>' not in r
+        assert '<span class="trove_fullpath">Database API » Python Database API</span>' not in r
 
     def test_add_remove_label(self):
         setup_trove_categories()
@@ -879,43 +880,43 @@ class TestProjectAdmin(TestController):
             'role_id': anon_id,
             'permission': 'create',
             'allow': 'true'})
-        assert {u'text': u'Inherited permission create from Anonymous',
-                u'has': u'inherit', u'name': u'create'} in r.json[admin_id]
-        assert {u'text': u'Inherited permission create from Anonymous',
-                u'has': u'inherit', u'name': u'create'} in r.json[mem_id]
-        assert {u'text': u'Has permission create', u'has':
-                u'yes', u'name': u'create'} in r.json[anon_id]
+        assert {'text': 'Inherited permission create from Anonymous',
+                'has': 'inherit', 'name': 'create'} in r.json[admin_id]
+        assert {'text': 'Inherited permission create from Anonymous',
+                'has': 'inherit', 'name': 'create'} in r.json[mem_id]
+        assert {'text': 'Has permission create', 'has':
+                'yes', 'name': 'create'} in r.json[anon_id]
         r = self.app.post('/admin/groups/change_perm', params={
             'role_id': anon_id,
             'permission': 'create',
             'allow': 'false'})
-        assert {u'text': u'Does not have permission create',
-                u'has': u'no', u'name': u'create'} in r.json[admin_id]
-        assert {u'text': u'Does not have permission create',
-                u'has': u'no', u'name': u'create'} in r.json[mem_id]
-        assert {u'text': u'Does not have permission create',
-                u'has': u'no', u'name': u'create'} in r.json[anon_id]
+        assert {'text': 'Does not have permission create',
+                'has': 'no', 'name': 'create'} in r.json[admin_id]
+        assert {'text': 'Does not have permission create',
+                'has': 'no', 'name': 'create'} in r.json[mem_id]
+        assert {'text': 'Does not have permission create',
+                'has': 'no', 'name': 'create'} in r.json[anon_id]
         # updates to Member inherit up
         r = self.app.post('/admin/groups/change_perm', params={
             'role_id': mem_id,
             'permission': 'create',
             'allow': 'true'})
-        assert {u'text': u'Inherited permission create from Member',
-                u'has': u'inherit', u'name': u'create'} in r.json[admin_id]
-        assert {u'text': u'Has permission create', u'has':
-                u'yes', u'name': u'create'} in r.json[mem_id]
-        assert {u'text': u'Does not have permission create',
-                u'has': u'no', u'name': u'create'} in r.json[anon_id]
+        assert {'text': 'Inherited permission create from Member',
+                'has': 'inherit', 'name': 'create'} in r.json[admin_id]
+        assert {'text': 'Has permission create', 'has':
+                'yes', 'name': 'create'} in r.json[mem_id]
+        assert {'text': 'Does not have permission create',
+                'has': 'no', 'name': 'create'} in r.json[anon_id]
         r = self.app.post('/admin/groups/change_perm', params={
             'role_id': mem_id,
             'permission': 'create',
             'allow': 'false'})
-        assert {u'text': u'Does not have permission create',
-                u'has': u'no', u'name': u'create'} in r.json[admin_id]
-        assert {u'text': u'Does not have permission create',
-                u'has': u'no', u'name': u'create'} in r.json[mem_id]
-        assert {u'text': u'Does not have permission create',
-                u'has': u'no', u'name': u'create'} in r.json[anon_id]
+        assert {'text': 'Does not have permission create',
+                'has': 'no', 'name': 'create'} in r.json[admin_id]
+        assert {'text': 'Does not have permission create',
+                'has': 'no', 'name': 'create'} in r.json[mem_id]
+        assert {'text': 'Does not have permission create',
+                'has': 'no', 'name': 'create'} in r.json[anon_id]
 
     def test_admin_extension_sidebar(self):
 
@@ -972,7 +973,7 @@ class TestExport(TestController):
         exportable_tools = AdminApp.exportable_tools_for(project)
         exportable_mount_points = [
             t.options.mount_point for t in exportable_tools]
-        assert_equals(exportable_mount_points, [u'admin', u'wiki', u'wiki2'])
+        assert_equals(exportable_mount_points, ['admin', 'wiki', 'wiki2'])
 
     def test_access(self):
         r = self.app.get('/admin/export',
@@ -1016,29 +1017,29 @@ class TestExport(TestController):
             exportable_mount_points = [
                 t.options.mount_point for t in exportable_tools]
             assert_equals(exportable_mount_points,
-                          [u'admin', u'search', u'wiki', u'wiki2'])
+                          ['admin', 'search', 'wiki', 'wiki2'])
 
     def test_tools_not_selected(self):
         r = self.app.post('/admin/export')
         assert_in('error', self.webflash(r))
 
     def test_bad_tool(self):
-        r = self.app.post('/admin/export', {'tools': u'search'})
+        r = self.app.post('/admin/export', {'tools': 'search'})
         assert_in('error', self.webflash(r))
 
     @mock.patch('allura.ext.admin.admin_main.export_tasks')
     def test_selected_one_tool(self, export_tasks):
-        r = self.app.post('/admin/export', {'tools': u'wiki'})
+        r = self.app.post('/admin/export', {'tools': 'wiki'})
         assert_in('ok', self.webflash(r))
         export_tasks.bulk_export.post.assert_called_once_with(
-            [u'wiki'], 'test.zip', send_email=True, with_attachments=False)
+            ['wiki'], 'test.zip', send_email=True, with_attachments=False)
 
     @mock.patch('allura.ext.admin.admin_main.export_tasks')
     def test_selected_multiple_tools(self, export_tasks):
-        r = self.app.post('/admin/export', {'tools': [u'wiki', u'wiki2']})
+        r = self.app.post('/admin/export', {'tools': ['wiki', 'wiki2']})
         assert_in('ok', self.webflash(r))
         export_tasks.bulk_export.post.assert_called_once_with(
-            [u'wiki', u'wiki2'], 'test.zip', send_email=True, with_attachments=False)
+            ['wiki', 'wiki2'], 'test.zip', send_email=True, with_attachments=False)
 
     @mock.patch('allura.model.session.project_doc_session')
     def test_export_in_progress(self, session):
@@ -1343,23 +1344,23 @@ class TestRestMountOrder(TestRestApiBase):
     @td.with_wiki
     def test_reorder(self):
         d1 = {
-            '0': u'sub1',
-            '1': u'wiki',
-            '2': u'admin'
+            '0': 'sub1',
+            '1': 'wiki',
+            '2': 'admin'
         }
         d2 = {
-            '0': u'wiki',
-            '1': u'sub1',
-            '2': u'admin'
+            '0': 'wiki',
+            '1': 'sub1',
+            '2': 'admin'
         }
 
         tool = {
-            u'icon': u'tool-admin',
-            u'is_anchored': False,
-            u'mount_point': u'sub1',
-            u'name': u'A Subproject',
-            u'tool_name': u'sub',
-            u'url': u'/p/test/sub1/'
+            'icon': 'tool-admin',
+            'is_anchored': False,
+            'mount_point': 'sub1',
+            'name': 'A Subproject',
+            'tool_name': 'sub',
+            'url': '/p/test/sub1/'
         }
 
         # Set initial order to d1
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index 307460f..653609e 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import calendar
 from datetime import datetime, time, timedelta
 from time import time as time_time
@@ -157,7 +158,7 @@ class TestAuth(TestController):
 
         args, kwargs = sendsimplemail.post.call_args
         assert_equal(sendsimplemail.post.call_count, 1)
-        assert_equal(kwargs['subject'], u'Update your %s password' % config['site_name'])
+        assert_equal(kwargs['subject'], 'Update your %s password' % config['site_name'])
         assert_in('/auth/forgotten_password/', kwargs['text'])
 
         assert_equal([], M.UserLoginDetails.query.find().all())  # no records created
@@ -371,7 +372,7 @@ class TestAuth(TestController):
 
         assert sendsimplemail.post.call_count == 1
         assert kwargs['toaddr'] == email_address
-        assert kwargs['subject'] == u'%s - Email address claim attempt' % config['site_name']
+        assert kwargs['subject'] == '%s - Email address claim attempt' % config['site_name']
         assert "You tried to add %s to your Allura account, " \
                "but it is already claimed by your %s account." % (email_address, user.username) in kwargs['text']
 
@@ -475,7 +476,7 @@ class TestAuth(TestController):
         args, kwargs = sendsimplemail.post.call_args
         assert sendsimplemail.post.call_count == 1
         assert kwargs['toaddr'] == email_address
-        assert kwargs['subject'] == u'%s - Email address claim attempt' % config['site_name']
+        assert kwargs['subject'] == '%s - Email address claim attempt' % config['site_name']
         assert "You tried to add %s to your Allura account, " \
                "but it is already claimed by your %s account." % (email_address, user.username) in kwargs['text']
 
@@ -1611,7 +1612,7 @@ To update your password on %s, please visit the following URL:
         sendmail.post.assert_called_once_with(
             sender='noreply@localhost',
             toaddr=email.email,
-            fromaddr=u'"{}" <{}>'.format(config['site_name'], config['forgemail.return_path']),
+            fromaddr='"{}" <{}>'.format(config['site_name'], config['forgemail.return_path']),
             reply_to=config['forgemail.return_path'],
             subject='Allura Password recovery',
             message_id=gen_message_id(),
diff --git a/Allura/allura/tests/functional/test_discuss.py b/Allura/allura/tests/functional/test_discuss.py
index 978ec33..e94bf53 100644
--- a/Allura/allura/tests/functional/test_discuss.py
+++ b/Allura/allura/tests/functional/test_discuss.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 e1e54d5..7558db9 100644
--- a/Allura/allura/tests/functional/test_feeds.py
+++ b/Allura/allura/tests/functional/test_feeds.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from formencode.variabledecode import variable_encode
 
 from allura.tests import TestController
@@ -44,7 +45,7 @@ class TestFeeds(TestController):
                     status='open',
                     description='This is a description'))),
             status=302)
-        title = u'Descri\xe7\xe3o e Arquitetura'.encode('utf-8')
+        title = 'Descri\xe7\xe3o e Arquitetura'.encode('utf-8')
         self.app.post(
             '/wiki/%s/update' % title,
             params=dict(
diff --git a/Allura/allura/tests/functional/test_gravatar.py b/Allura/allura/tests/functional/test_gravatar.py
index 72e0b99..b07e4cd 100644
--- a/Allura/allura/tests/functional/test_gravatar.py
+++ b/Allura/allura/tests/functional/test_gravatar.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from urlparse import urlparse, parse_qs
 
 import tg
@@ -34,7 +35,7 @@ class TestGravatar(TestController):
         assert expected_id == actual_id
 
     def test_unicode_id(self):
-        email = u'Vin\u00EDcius@example.com'
+        email = 'Vin\u00EDcius@example.com'
         expected_id = 'e00968255d68523b034a6a39c522efdb'
         actual_id = gravatar.id(email)
         assert expected_id == actual_id, 'Expected gravitar ID %s, got %s' % (
diff --git a/Allura/allura/tests/functional/test_home.py b/Allura/allura/tests/functional/test_home.py
index 768a973..4ab8147 100644
--- a/Allura/allura/tests/functional/test_home.py
+++ b/Allura/allura/tests/functional/test_home.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import json
 import re
 import os
@@ -61,7 +62,7 @@ class TestProjectHome(TestController):
                                }])
                 break
         else:
-            raise AssertionError(u'Did not find sub1 subproject in menu results: {}'.format(r.json['menu']))
+            raise AssertionError('Did not find sub1 subproject in menu results: {}'.format(r.json['menu']))
         for m in r.json['menu']:
             if m['mount_point'] == 'wiki':
                 assert_in({'className': 'admin_modal',
@@ -78,7 +79,7 @@ class TestProjectHome(TestController):
                            }, m['admin_options'])
                 break
         else:
-            raise AssertionError(u'Did not find wiki in menu results: {}'.format(r.json['menu']))
+            raise AssertionError('Did not find wiki in menu results: {}'.format(r.json['menu']))
 
     @td.with_wiki
     def test_project_group_nav(self):
@@ -92,7 +93,7 @@ class TestProjectHome(TestController):
         menu = response.json['menu']
         wiki_group = menu[-2]
         wikis = wiki_group.pop('children')
-        assert_equal({'url': '/p/test/_list/wiki', 'name': u'Wiki \u25be', 'mount_point': None,
+        assert_equal({'url': '/p/test/_list/wiki', 'name': 'Wiki \u25be', 'mount_point': None,
                       'icon': 'tool-wiki', 'tool_name': 'wiki', 'is_anchored': False}, wiki_group)
         assert_equal(len(wikis), 2)
         assert_in({'url': '/p/test/wiki/', 'name': 'Wiki', 'mount_point': 'wiki',
@@ -187,8 +188,8 @@ class TestProjectHome(TestController):
         r = self.app.get('/p/test/users', status=200)
         j = json.loads(r.body)
         expected = [{
-            'value': u'test-admin',
-            'label': u'Test Admin (test-admin)'
+            'value': 'test-admin',
+            'label': 'Test Admin (test-admin)'
         }]
         assert_equal(j['options'], expected)
 
diff --git a/Allura/allura/tests/functional/test_nav.py b/Allura/allura/tests/functional/test_nav.py
index 8fb2f78..a50579f 100644
--- a/Allura/allura/tests/functional/test_nav.py
+++ b/Allura/allura/tests/functional/test_nav.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 211b745..2e7d65a 100644
--- a/Allura/allura/tests/functional/test_neighborhood.py
+++ b/Allura/allura/tests/functional/test_neighborhood.py
@@ -16,6 +16,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import json
 import os
 from cStringIO import StringIO
@@ -747,7 +748,7 @@ class TestNeighborhood(TestController):
         # check the labels and trove cats
         r = self.app.get('/adobe/testtemp/admin/trove')
         assert 'mmi' in r
-        assert u'Communications » Telephony' in r
+        assert 'Communications » Telephony' in r
         assert '5 - Production/Stable' in r
         # check the wiki text
         r = self.app.get('/adobe/testtemp/wiki/').follow()
@@ -1003,7 +1004,7 @@ class TestPhoneVerificationOnProjectRegistration(TestController):
             r = self.app.get('/p/verify_phone', {'number': '555-444-3333'})
         expected = {
             'status': 'error',
-            'error': u'&lt;script&gt;alert(&#34;hacked&#34;);&lt;/script&gt;',
+            'error': '&lt;script&gt;alert(&#34;hacked&#34;);&lt;/script&gt;',
         }
         assert_equal(r.json, expected)
 
@@ -1017,7 +1018,7 @@ class TestPhoneVerificationOnProjectRegistration(TestController):
             r = self.app.get('/p/verify_phone', {'number': '1-555-444-9999'})
             assert_equal(r.json, {
                 'status': 'error',
-                'error': u'That phone number has already been used.'
+                'error': 'That phone number has already been used.'
             })
 
     def test_check_phone_verification_no_params(self):
@@ -1072,7 +1073,7 @@ class TestPhoneVerificationOnProjectRegistration(TestController):
             r = self.app.get('/p/check_phone_verification', {'pin': '1234'})
         expected = {
             'status': 'error',
-            'error': u'&lt;script&gt;alert(&#34;hacked&#34;);&lt;/script&gt;',
+            'error': '&lt;script&gt;alert(&#34;hacked&#34;);&lt;/script&gt;',
         }
         assert_equal(r.json, expected)
 
diff --git a/Allura/allura/tests/functional/test_personal_dashboard.py b/Allura/allura/tests/functional/test_personal_dashboard.py
index 217c470..01e3e8f 100644
--- a/Allura/allura/tests/functional/test_personal_dashboard.py
+++ b/Allura/allura/tests/functional/test_personal_dashboard.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 1ba033b..fc8ba1e 100644
--- a/Allura/allura/tests/functional/test_rest.py
+++ b/Allura/allura/tests/functional/test_rest.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 e6a6bc7..7438a37 100644
--- a/Allura/allura/tests/functional/test_root.py
+++ b/Allura/allura/tests/functional/test_root.py
@@ -28,6 +28,7 @@ functional tests exercise the whole application and its WSGI stack.
 Please read http://pythonpaste.org/webtest/ for more information.
 
 """
+from __future__ import unicode_literals
 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 3a1a72b..3d3315b 100644
--- a/Allura/allura/tests/functional/test_search.py
+++ b/Allura/allura/tests/functional/test_search.py
@@ -14,6 +14,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 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 8b23c1e..b75f51d 100644
--- a/Allura/allura/tests/functional/test_site_admin.py
+++ b/Allura/allura/tests/functional/test_site_admin.py
@@ -16,6 +16,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import json
 import datetime as dt
 import bson
@@ -471,9 +472,9 @@ class TestUserDetails(TestController):
         # list of projects
         projects = r.html.findAll('fieldset')[-1]
         projects = [e.getText() for e in projects.findAll('li')]
-        assert_in(u'Test 2\n\u2013\nAdmin\n', projects)
-        assert_in(u'Test Project\n\u2013\nAdmin\n', projects)
-        assert_in(u'Adobe project 1\n\u2013\nAdmin\n', projects)
+        assert_in('Test 2\n\u2013\nAdmin\n', projects)
+        assert_in('Test Project\n\u2013\nAdmin\n', projects)
+        assert_in('Adobe project 1\n\u2013\nAdmin\n', projects)
 
     @patch('allura.model.auth.request')
     @patch('allura.lib.helpers.request')
@@ -501,14 +502,14 @@ class TestUserDetails(TestController):
 
     def test_add_comment(self):
         r = self.app.get('/nf/admin/user/test-user')
-        assert_not_in(u'Comment by test-admin: I was hêre!', r)
+        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]
         assert_equal(form['username'].value, 'test-user')
-        form['comment'] = u'I was hêre!'
+        form['comment'] = 'I was hêre!'
         r = form.submit()
-        assert_in(u'Comment added', self.webflash(r))
+        assert_in('Comment added', self.webflash(r))
         r = self.app.get('/nf/admin/user/test-user')
-        assert_in(u'Comment by test-admin: I was hêre!', r)
+        assert_in('Comment by test-admin: I was hêre!', r)
 
     def test_disable_user(self):
         # user was not pending
@@ -522,7 +523,7 @@ class TestUserDetails(TestController):
         with td.audits('Account disabled', user=True):
             r = form.submit()
             assert_equal(M.AuditLog.query.find().count(), 1)
-        assert_in(u'User disabled', self.webflash(r))
+        assert_in('User disabled', self.webflash(r))
         assert_equal(M.User.by_username('test-user-3').disabled, True)
         assert_equal(M.User.by_username('test-user-3').pending, False)
 
@@ -541,7 +542,7 @@ class TestUserDetails(TestController):
         with td.audits('Account disabled', user=True):
             r = form.submit()
             assert_equal(M.AuditLog.query.find().count(), 1)
-        assert_in(u'User disabled', self.webflash(r))
+        assert_in('User disabled', self.webflash(r))
         assert_equal(M.User.by_username('test-user-3').disabled, True)
         assert_equal(M.User.by_username('test-user-3').pending, True)
 
@@ -560,7 +561,7 @@ class TestUserDetails(TestController):
         with td.audits('Account enabled', user=True):
             r = form.submit()
             assert_equal(M.AuditLog.query.find().count(), 1)
-        assert_in(u'User enabled', self.webflash(r))
+        assert_in('User enabled', self.webflash(r))
         assert_equal(M.User.by_username('test-user-3').disabled, False)
         assert_equal(M.User.by_username('test-user-3').pending, False)
 
@@ -579,7 +580,7 @@ class TestUserDetails(TestController):
         with td.audits('Account enabled', user=True):
             r = form.submit()
             assert_equal(M.AuditLog.query.find().count(), 1)
-        assert_in(u'User enabled', self.webflash(r))
+        assert_in('User enabled', self.webflash(r))
         assert_equal(M.User.by_username('test-user-3').disabled, False)
         assert_equal(M.User.by_username('test-user-3').pending, False)
 
@@ -598,7 +599,7 @@ class TestUserDetails(TestController):
         with td.audits('Account enabled', user=True):
             r = form.submit()
             assert_equal(M.AuditLog.query.find().count(), 1)
-        assert_in(u'User enabled', self.webflash(r))
+        assert_in('User enabled', self.webflash(r))
         assert_equal(M.User.by_username('test-user-3').disabled, False)
         assert_equal(M.User.by_username('test-user-3').pending, False)
 
@@ -617,7 +618,7 @@ class TestUserDetails(TestController):
         with td.audits('Account changed to pending', user=True):
             r = form.submit()
             assert_equal(M.AuditLog.query.find().count(), 1)
-        assert_in(u'Set user status to pending', self.webflash(r))
+        assert_in('Set user status to pending', self.webflash(r))
         assert_equal(M.User.by_username('test-user-3').disabled, False)
         assert_equal(M.User.by_username('test-user-3').pending, True)
 
@@ -636,7 +637,7 @@ class TestUserDetails(TestController):
         with td.audits('Account changed to pending', user=True):
             r = form.submit()
             assert_equal(M.AuditLog.query.find().count(), 1)
-        assert_in(u'Set user status to pending', self.webflash(r))
+        assert_in('Set user status to pending', self.webflash(r))
         assert_equal(M.User.by_username('test-user-3').disabled, False)
         assert_equal(M.User.by_username('test-user-3').pending, True)
 
@@ -723,7 +724,7 @@ To update your password on %s, please visit the following URL:
         sendmail.post.assert_called_once_with(
             sender='noreply@localhost',
             toaddr='test-user@example.org',
-            fromaddr=u'"{}" <{}>'.format(config['site_name'], config['forgemail.return_path']),
+            fromaddr='"{}" <{}>'.format(config['site_name'], config['forgemail.return_path']),
             reply_to=config['forgemail.return_path'],
             subject='Allura Password recovery',
             message_id=gen_message_id(),
@@ -747,14 +748,14 @@ class TestDeleteProjects(TestController):
 
     def test_projects_populated_from_get_params(self):
         r = self.app.get('/nf/admin/delete_projects/')
-        assert_equal(self.delete_form(r)['projects'].value, u'')
+        assert_equal(self.delete_form(r)['projects'].value, '')
         link = '/nf/admin/delete_projects/?projects=/p/test/++++%23+comment%0A/adobe/adobe-1/%0A/p/test2/'
         link += '&reason=The%0AReason&disable_users=True'
         r = self.app.get(link)
         form = self.delete_form(r)
-        assert_equal(form['projects'].value, u'/p/test/    # comment\n/adobe/adobe-1/\n/p/test2/')
-        assert_equal(form['reason'].value, u'The\nReason')
-        assert_equal(form['disable_users'].value, u'on')
+        assert_equal(form['projects'].value, '/p/test/    # comment\n/adobe/adobe-1/\n/p/test2/')
+        assert_equal(form['reason'].value, 'The\nReason')
+        assert_equal(form['disable_users'].value, 'on')
 
     def test_confirm_step_values(self):
         r = self.app.get('/nf/admin/delete_projects/')
diff --git a/Allura/allura/tests/functional/test_static.py b/Allura/allura/tests/functional/test_static.py
index 6d66d33..392af13 100644
--- a/Allura/allura/tests/functional/test_static.py
+++ b/Allura/allura/tests/functional/test_static.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from allura.tests import TestController
 
 
diff --git a/Allura/allura/tests/functional/test_subscriber.py b/Allura/allura/tests/functional/test_subscriber.py
index 93b822e..aae83a3 100644
--- a/Allura/allura/tests/functional/test_subscriber.py
+++ b/Allura/allura/tests/functional/test_subscriber.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 08607cf..1bf57db 100644
--- a/Allura/allura/tests/functional/test_tool_list.py
+++ b/Allura/allura/tests/functional/test_tool_list.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 2dc438f..850a3bb 100644
--- a/Allura/allura/tests/functional/test_trovecategory.py
+++ b/Allura/allura/tests/functional/test_trovecategory.py
@@ -14,6 +14,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 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 8f8f027..6ed96a8 100644
--- a/Allura/allura/tests/functional/test_user_profile.py
+++ b/Allura/allura/tests/functional/test_user_profile.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import mock
 import tg
 from nose.tools import assert_equal, assert_in, assert_not_in
@@ -121,12 +122,12 @@ class TestUserProfile(TestController):
 
         sendsimplemail.post.assert_called_once_with(
             cc=User.by_username('test-admin').get_pref('email_address'),
-            text=u'test message\n\n---\n\nThis message was sent to you via the Allura web mail form.  You may reply to this message directly, or send a message to Test Admin at http://localhost/u/test-admin/profile/send_message\n',
+            text='test message\n\n---\n\nThis message was sent to you via the Allura web mail form.  You may reply to this message directly, or send a message to Test Admin at http://localhost/u/test-admin/profile/send_message\n',
             toaddr=User.by_username('test-user').get_pref('email_address'),
             fromaddr=User.by_username('test-admin').get_pref('email_address'),
             reply_to=User.by_username('test-admin').get_pref('email_address'),
-            message_id=u'id',
-            subject=u'test subject')
+            message_id='id',
+            subject='test subject')
         sendsimplemail.reset_mock()
         self.app.post('/u/test-user/profile/send_user_message',
                       params={'subject': 'test subject',
@@ -134,12 +135,12 @@ class TestUserProfile(TestController):
 
         sendsimplemail.post.assert_called_once_with(
             cc=None,
-            text=u'test message\n\n---\n\nThis message was sent to you via the Allura web mail form.  You may reply to this message directly, or send a message to Test Admin at http://localhost/u/test-admin/profile/send_message\n',
+            text='test message\n\n---\n\nThis message was sent to you via the Allura web mail form.  You may reply to this message directly, or send a message to Test Admin at http://localhost/u/test-admin/profile/send_message\n',
             toaddr=User.by_username('test-user').get_pref('email_address'),
             fromaddr=User.by_username('test-admin').get_pref('email_address'),
             reply_to=User.by_username('test-admin').get_pref('email_address'),
-            message_id=u'id',
-            subject=u'test subject')
+            message_id='id',
+            subject='test subject')
 
         check.return_value = False
         response = self.app.get(
diff --git a/Allura/allura/tests/model/__init__.py b/Allura/allura/tests/model/__init__.py
index c194980..b7d0eab 100644
--- a/Allura/allura/tests/model/__init__.py
+++ b/Allura/allura/tests/model/__init__.py
@@ -18,3 +18,5 @@
 #       under the License.
 
 """Model test suite for the models of the application."""
+
+from __future__ import unicode_literals
\ No newline at end of file
diff --git a/Allura/allura/tests/model/test_artifact.py b/Allura/allura/tests/model/test_artifact.py
index 1e63813..06b2b2a 100644
--- a/Allura/allura/tests/model/test_artifact.py
+++ b/Allura/allura/tests/model/test_artifact.py
@@ -20,6 +20,7 @@
 """
 Model tests for artifact
 """
+from __future__ import unicode_literals
 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 47dc8b6..88df750 100644
--- a/Allura/allura/tests/model/test_auth.py
+++ b/Allura/allura/tests/model/test_auth.py
@@ -20,6 +20,7 @@
 """
 Model tests for auth
 """
+from __future__ import unicode_literals
 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 d470c87..162c235 100644
--- a/Allura/allura/tests/model/test_discussion.py
+++ b/Allura/allura/tests/model/test_discussion.py
@@ -20,6 +20,7 @@
 """
 Model tests for artifact
 """
+from __future__ import unicode_literals
 from cStringIO import StringIO
 import time
 from datetime import datetime, timedelta
@@ -200,10 +201,10 @@ def test_attachment_methods():
     fs.filename = 'fake.txt'
     fs.type = 'text/plain'
     fs.file = StringIO('this is the content of the fake file\n')
-    p = t.post(text=u'test message', forum=None, subject='', file_info=fs)
+    p = t.post(text='test message', forum=None, subject='', file_info=fs)
     ThreadLocalORMSession.flush_all()
     n = M.Notification.query.get(
-        subject=u'[test:wiki] Test comment notification')
+        subject='[test:wiki] Test comment notification')
     url = h.absurl('{}attachment/{}'.format(p.url(), fs.filename))
     assert_in(
         '\nAttachments:\n\n'
@@ -265,10 +266,10 @@ def test_notification_two_attaches():
     fs2.filename = 'fake2.txt'
     fs2.type = 'text/plain'
     fs2.file = StringIO('this is the content of the fake file\n')
-    p = t.post(text=u'test message', forum=None, subject='', file_info=[fs1, fs2])
+    p = t.post(text='test message', forum=None, subject='', file_info=[fs1, fs2])
     ThreadLocalORMSession.flush_all()
     n = M.Notification.query.get(
-        subject=u'[test:wiki] Test comment notification')
+        subject='[test:wiki] Test comment notification')
     base_url = h.absurl('{}attachment/'.format(p.url()))
     assert_in(
         '\nAttachments:\n\n'
diff --git a/Allura/allura/tests/model/test_filesystem.py b/Allura/allura/tests/model/test_filesystem.py
index 30ab9e9..665ec22 100644
--- a/Allura/allura/tests/model/test_filesystem.py
+++ b/Allura/allura/tests/model/test_filesystem.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 from unittest import TestCase
 from cStringIO import StringIO
@@ -123,26 +124,26 @@ class TestFile(TestCase):
         self._assert_content(f, 'test2')
 
     def test_serve_embed(self):
-        f = File.from_data(u'te s\u0b6e1.txt', 'test1')
+        f = File.from_data('te s\u0b6e1.txt', 'test1')
         self.session.flush()
         with patch('allura.lib.utils.tg.request', Request.blank('/')), \
                 patch('allura.lib.utils.tg.response', Response()) as response, \
                 patch('allura.lib.utils.etag_cache') as etag_cache:
             response_body = list(f.serve())
-            etag_cache.assert_called_once_with(u'{}?{}'.format(f.filename,
+            etag_cache.assert_called_once_with('{}?{}'.format(f.filename,
                                                                f._id.generation_time).encode('utf-8'))
             assert_equal(['test1'], response_body)
             assert_equal(response.content_type, f.content_type)
             assert 'Content-Disposition' not in response.headers
 
     def test_serve_embed_false(self):
-        f = File.from_data(u'te s\u0b6e1.txt', 'test1')
+        f = File.from_data('te s\u0b6e1.txt', 'test1')
         self.session.flush()
         with patch('allura.lib.utils.tg.request', Request.blank('/')), \
                 patch('allura.lib.utils.tg.response', Response()) as response, \
                 patch('allura.lib.utils.etag_cache') as etag_cache:
             response_body = list(f.serve(embed=False))
-            etag_cache.assert_called_once_with(u'{}?{}'.format(f.filename,
+            etag_cache.assert_called_once_with('{}?{}'.format(f.filename,
                                                                f._id.generation_time).encode('utf-8'))
             assert_equal(['test1'], response_body)
             assert_equal(response.content_type, f.content_type)
@@ -209,7 +210,7 @@ class TestFile(TestCase):
             b'Strukturpr\xfcfung.dvi', fp,
             save_original=True)
         assert type(attachment) != tuple   # tuple is for (img, thumb) pairs
-        assert_equal(attachment.filename, u'Strukturpr\xfcfung.dvi')
+        assert_equal(attachment.filename, 'Strukturpr\xfcfung.dvi')
 
     def _assert_content(self, f, content):
         result = f.rfile().read()
diff --git a/Allura/allura/tests/model/test_monq.py b/Allura/allura/tests/model/test_monq.py
index 4ba2f0b..e42c940 100644
--- a/Allura/allura/tests/model/test_monq.py
+++ b/Allura/allura/tests/model/test_monq.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 b1ba8c3..bb62787 100644
--- a/Allura/allura/tests/model/test_neighborhood.py
+++ b/Allura/allura/tests/model/test_neighborhood.py
@@ -20,6 +20,7 @@
 """
 Model tests for neighborhood
 """
+from __future__ import unicode_literals
 from nose.tools import with_setup
 
 from allura import model as M
@@ -56,11 +57,11 @@ def test_neighborhood():
     assert neighborhood.get_max_projects() == 500
 
     # Check picker css styles
-    test_css_dict = {'barontop': u'#444',
-                     'titlebarbackground': u'#555',
-                     'projecttitlefont': u'arial,sans-serif',
-                     'projecttitlecolor': u'#333',
-                     'titlebarcolor': u'#666'}
+    test_css_dict = {'barontop': '#444',
+                     'titlebarbackground': '#555',
+                     'projecttitlefont': 'arial,sans-serif',
+                     'projecttitlecolor': '#333',
+                     'titlebarcolor': '#666'}
     css_text = neighborhood.compile_css_for_picker(test_css_dict)
     assert '#333' in css_text
     assert '#444' in css_text
diff --git a/Allura/allura/tests/model/test_notification.py b/Allura/allura/tests/model/test_notification.py
index d154bd7..684d3be 100644
--- a/Allura/allura/tests/model/test_notification.py
+++ b/Allura/allura/tests/model/test_notification.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 c565f5d..d7e4ee6 100644
--- a/Allura/allura/tests/model/test_oauth.py
+++ b/Allura/allura/tests/model/test_oauth.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 
+from __future__ import unicode_literals
 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 84eb0af..ea06c69 100644
--- a/Allura/allura/tests/model/test_project.py
+++ b/Allura/allura/tests/model/test_project.py
@@ -20,6 +20,7 @@
 """
 Model tests for project
 """
+from __future__ import unicode_literals
 from nose import with_setup
 from nose.tools import assert_equals, assert_in
 from tg import tmpl_context as c
@@ -187,7 +188,7 @@ def test_project_disabled_users():
 
 def test_screenshot_unicode_serialization():
     p = M.Project.query.get(shortname='test')
-    screenshot_unicode = M.ProjectFile(project_id=p._id, category='screenshot', caption=u"ConSelección", filename=u'ConSelección.jpg')
+    screenshot_unicode = M.ProjectFile(project_id=p._id, category='screenshot', caption="ConSelección", filename='ConSelección.jpg')
     screenshot_ascii = M.ProjectFile(project_id=p._id, category='screenshot', caption='test-screenshot', filename='test_file.jpg')
     ThreadLocalORMSession.flush_all()
 
@@ -196,7 +197,7 @@ def test_screenshot_unicode_serialization():
 
     assert len(screenshots) == 2
     assert screenshots[0]['url'] == 'http://localhost/p/test/screenshot/ConSelecci%C3%B3n.jpg'
-    assert screenshots[0]['caption'] == u"ConSelección"
+    assert screenshots[0]['caption'] == "ConSelección"
     assert screenshots[0]['thumbnail_url'] == 'http://localhost/p/test/screenshot/ConSelecci%C3%B3n.jpg/thumb'
 
     assert screenshots[1]['url'] == 'http://localhost/p/test/screenshot/test_file.jpg'
diff --git a/Allura/allura/tests/model/test_repo.py b/Allura/allura/tests/model/test_repo.py
index 5007d28..4d77e67 100644
--- a/Allura/allura/tests/model/test_repo.py
+++ b/Allura/allura/tests/model/test_repo.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from datetime import datetime
 from collections import defaultdict, OrderedDict
 
@@ -99,12 +100,12 @@ class RepoTestBase(unittest.TestCase):
         repo = M.repository.Repository(tool='git')
         cmd_cats = repo.clone_command_categories(anon=False)
         assert_equal(cmd_cats, [
-            {'key': 'file', 'name': 'File', 'title': u'Filesystem'}
+            {'key': 'file', 'name': 'File', 'title': 'Filesystem'}
         ])
 
         cmd_cats = repo.clone_command_categories(anon=True)
         assert_equal(cmd_cats, [
-            {'key': 'file', 'name': 'File', 'title': u'Filesystem'}
+            {'key': 'file', 'name': 'File', 'title': 'Filesystem'}
         ])
 
         repo = M.repository.Repository(tool='something-else')  # no "something-else" in config so will use defaults
diff --git a/Allura/allura/tests/model/test_timeline.py b/Allura/allura/tests/model/test_timeline.py
index 6f7ae94..0ca22d5 100644
--- a/Allura/allura/tests/model/test_timeline.py
+++ b/Allura/allura/tests/model/test_timeline.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 6f5f1b9..e8be071 100644
--- a/Allura/allura/tests/scripts/test_create_sitemap_files.py
+++ b/Allura/allura/tests/scripts/test_create_sitemap_files.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 c128f8c..cbb4767 100644
--- a/Allura/allura/tests/scripts/test_delete_projects.py
+++ b/Allura/allura/tests/scripts/test_delete_projects.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from ming.odm import session, Mapper, ThreadLocalODMSession
 from mock import patch
 from tg import app_globals as g
@@ -133,8 +134,8 @@ class TestDeleteProjects(TestController):
         self.proj.add_user(dev, ['Developer'])
         ThreadLocalODMSession.flush_all()
         g.credentials.clear()
-        proj = u'p/{}'.format(self.p_shortname)
-        msg = u'Account disabled because project /{} is deleted. Reason: The Reason'.format(proj)
+        proj = 'p/{}'.format(self.p_shortname)
+        msg = 'Account disabled because project /{} is deleted. Reason: The Reason'.format(proj)
         opts = ['-r', 'The Reason', proj]
         if disable:
             opts.insert(0, '--disable-users')
diff --git a/Allura/allura/tests/scripts/test_reindexes.py b/Allura/allura/tests/scripts/test_reindexes.py
index d6dbeb0..90ede90 100644
--- a/Allura/allura/tests/scripts/test_reindexes.py
+++ b/Allura/allura/tests/scripts/test_reindexes.py
@@ -14,6 +14,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 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 9421fe4..8005fbc 100644
--- a/Allura/allura/tests/templates/jinja_master/test_lib.py
+++ b/Allura/allura/tests/templates/jinja_master/test_lib.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 3ddbd04..25e39c2 100644
--- a/Allura/allura/tests/test_app.py
+++ b/Allura/allura/tests/test_app.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from tg import tmpl_context as c
 import mock
 from ming.base import Object
@@ -138,7 +139,7 @@ def test_handle_artifact_unicode(qg):
 
     a = app.Application(c.project, c.app.config)
 
-    msg = dict(payload=u'foo ƒ†©¥˙¨ˆ', message_id=1, headers={})
+    msg = dict(payload='foo ƒ†©¥˙¨ˆ', message_id=1, headers={})
     a.handle_artifact_message(ticket, msg)
     assert_equal(post.attach.call_args[0][1].getvalue(), 'foo ƒ†©¥˙¨ˆ')
 
diff --git a/Allura/allura/tests/test_commands.py b/Allura/allura/tests/test_commands.py
index 3ad18b6..22925b7 100644
--- a/Allura/allura/tests/test_commands.py
+++ b/Allura/allura/tests/test_commands.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 7261711..74777ab 100644
--- a/Allura/allura/tests/test_decorators.py
+++ b/Allura/allura/tests/test_decorators.py
@@ -14,6 +14,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 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 67c0807..6b61cec 100644
--- a/Allura/allura/tests/test_diff.py
+++ b/Allura/allura/tests/test_diff.py
@@ -16,6 +16,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import unittest
 
 from allura.lib.diff import HtmlSideBySideDiff
@@ -143,4 +144,4 @@ class TestHtmlSideBySideDiff(unittest.TestCase):
         a = ['строка']
         b = ['измененная строка']
         html = self.diff.make_table(a, b, 'file a', 'file b')
-        assert u'строка' in html
+        assert 'строка' in html
diff --git a/Allura/allura/tests/test_dispatch.py b/Allura/allura/tests/test_dispatch.py
index 19f9652..b80cead 100644
--- a/Allura/allura/tests/test_dispatch.py
+++ b/Allura/allura/tests/test_dispatch.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from allura.tests import TestController
 
 app = None
diff --git a/Allura/allura/tests/test_globals.py b/Allura/allura/tests/test_globals.py
index f7b2be4..6e3a702 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 
+from __future__ import unicode_literals
 import re
 import os
 import allura
@@ -172,8 +173,8 @@ def test_macro_gittip_button():
         r = g.markdown_wiki.convert('[[gittip_button username=test]]')
     assert_equal(
         r,
-        u'<div class="markdown_content"><p><iframe height="22pt" src="https://www.gittip.com/test/widget.html" '
-        u'style="border: 0; margin: 0; padding: 0;" width="48pt"></iframe></p>\n</div>')
+        '<div class="markdown_content"><p><iframe height="22pt" src="https://www.gittip.com/test/widget.html" '
+        'style="border: 0; margin: 0; padding: 0;" width="48pt"></iframe></p>\n</div>')
 
 
 def test_macro_neighborhood_feeds():
@@ -231,26 +232,26 @@ def test_macro_members():
 @with_setup(setUp)
 def test_macro_members_escaping():
     user = M.User.by_username('test-admin')
-    user.display_name = u'Test Admin <script>'
+    user.display_name = 'Test Admin <script>'
     r = g.markdown_wiki.convert('[[members]]')
     assert_equal(r.replace('\n', '').replace('\t', ''),
-                 u'<div class="markdown_content"><h6>Project Members:</h6>'
-                 u'<ul class="md-users-list">'
-                 u'<li><a href="/u/test-admin/">Test Admin &lt;script&gt;</a> (admin)</li>'
-                 u'</ul></div>')
+                 '<div class="markdown_content"><h6>Project Members:</h6>'
+                 '<ul class="md-users-list">'
+                 '<li><a href="/u/test-admin/">Test Admin &lt;script&gt;</a> (admin)</li>'
+                 '</ul></div>')
 
 
 @with_setup(setUp)
 def test_macro_project_admins():
     user = M.User.by_username('test-admin')
-    user.display_name = u'Test Ådmin <script>'
+    user.display_name = 'Test Ådmin <script>'
     with h.push_context('test', neighborhood='Projects'):
         r = g.markdown_wiki.convert('[[project_admins]]')
     assert_equal(r.replace('\n', ''),
-                 u'<div class="markdown_content"><h6>Project Admins:</h6>'
-                 u'<ul class="md-users-list">'
-                 u'    <li><a href="/u/test-admin/">Test \xc5dmin &lt;script&gt;</a></li>'
-                 u'</ul></div>')
+                 '<div class="markdown_content"><h6>Project Admins:</h6>'
+                 '<ul class="md-users-list">'
+                 '    <li><a href="/u/test-admin/">Test \xc5dmin &lt;script&gt;</a></li>'
+                 '</ul></div>')
 
 
 @with_setup(setUp)
@@ -618,12 +619,12 @@ def test_hideawards_macro():
 
     app_config_id = ObjectId()
     award = M.Award(app_config_id=app_config_id)
-    award.short = u'Award short'
-    award.full = u'Award full'
+    award.short = 'Award short'
+    award.full = 'Award full'
     award.created_by_neighborhood_id = p_nbhd._id
 
     project = M.Project.query.get(
-        neighborhood_id=p_nbhd._id, shortname=u'test')
+        neighborhood_id=p_nbhd._id, shortname='test')
 
     M.AwardGrant(
         award=award,
@@ -705,8 +706,8 @@ class TestCachedMarkdown(unittest.TestCase):
     def setUp(self):
         self.md = ForgeMarkdown()
         self.post = M.Post()
-        self.post.text = u'**bold**'
-        self.expected_html = u'<p><strong>bold</strong></p>'
+        self.post.text = '**bold**'
+        self.expected_html = '<p><strong>bold</strong></p>'
 
     def test_bad_source_field_name(self):
         self.assertRaises(AttributeError, self.md.cached_convert,
@@ -719,8 +720,8 @@ class TestCachedMarkdown(unittest.TestCase):
 
     @patch.dict('allura.lib.app_globals.config', markdown_cache_threshold='-0.01')
     def test_non_ascii(self):
-        self.post.text = u'å∫ç'
-        expected = u'<p>å∫ç</p>'
+        self.post.text = 'å∫ç'
+        expected = '<p>å∫ç</p>'
         # test with empty cache
         self.assertEqual(expected, self.md.cached_convert(self.post, 'text'))
         # test with primed cache
@@ -738,7 +739,7 @@ class TestCachedMarkdown(unittest.TestCase):
     @patch.dict('allura.lib.app_globals.config', markdown_cache_threshold='-0.01')
     def test_stale_cache(self):
         old = self.md.cached_convert(self.post, 'text')
-        self.post.text = u'new, different source text'
+        self.post.text = 'new, different source text'
         html = self.md.cached_convert(self.post, 'text')
         self.assertNotEqual(old, html)
         self.assertEqual(html, self.post.text_cache.html)
@@ -755,7 +756,7 @@ class TestCachedMarkdown(unittest.TestCase):
             self.assertEqual(html, self.expected_html)
             self.assertIsInstance(html, Markup)
             self.assertFalse(convert_func.called)
-            self.post.text = u"text [[macro]] pass"
+            self.post.text = "text [[macro]] pass"
             html = self.md.cached_convert(self.post, 'text')
             self.assertTrue(convert_func.called)
 
@@ -795,33 +796,33 @@ class TestEmojis(unittest.TestCase):
 
     def test_markdown_emoji_atomic(self):
         output = g.markdown.convert(':+1:')
-        assert u'<p>\U0001F44D</p>' in output
+        assert '<p>\U0001F44D</p>' in output
         output = g.markdown.convert(':Bosnia_&_Herzegovina:')
-        assert u'<p>\U0001F1E7\U0001F1E6</p>' in output
-        output = g.markdown.convert(u':Åland_Islands:') # emoji code with non-asciii charactor
-        assert u'<p>\U0001F1E6\U0001F1FD</p>' in output
+        assert '<p>\U0001F1E7\U0001F1E6</p>' in output
+        output = g.markdown.convert(':Åland_Islands:') # emoji code with non-asciii charactor
+        assert '<p>\U0001F1E6\U0001F1FD</p>' in output
 
     def test_markdown_emoji_with_text(self):
         output = g.markdown.convert('Thumbs up emoji :+1: wow!')
-        assert u'<p>Thumbs up emoji \U0001F44D wow!</p>' in output
-        output = g.markdown.convert(u'More emojis :+1::camel::three_o’clock: wow!')
-        assert u'<p>More emojis \U0001F44D\U0001F42B\U0001F552 wow!</p>' in output
+        assert '<p>Thumbs up emoji \U0001F44D wow!</p>' in output
+        output = g.markdown.convert('More emojis :+1::camel::three_o’clock: wow!')
+        assert '<p>More emojis \U0001F44D\U0001F42B\U0001F552 wow!</p>' in output
         output = g.markdown.convert(':man_bouncing_ball_medium-light_skin_tone:emoji:+1:')
-        assert u'<p>\U000026F9\U0001F3FC\U0000200D\U00002642\U0000FE0Femoji\U0001F44D</p>' in output
+        assert '<p>\U000026F9\U0001F3FC\U0000200D\U00002642\U0000FE0Femoji\U0001F44D</p>' in output
 
     def test_markdown_emoji_in_code(self):
         output = g.markdown.convert('This will not become an emoji `:+1:`')
-        assert_in(u'<p>This will not become an emoji <code>:+1:</code></p>', output)
-        output = g.markdown.convert(u'```html\n<p>:camel:</p>\n```')
-        assert_in(u':camel:', output)
-        output = g.markdown.convert(u'~~~\n:camel:\n~~~')
-        assert_in(u'<span class="p">:</span><span class="n">camel</span><span class="p">:</span>', output)
+        assert_in('<p>This will not become an emoji <code>:+1:</code></p>', output)
+        output = g.markdown.convert('```html\n<p>:camel:</p>\n```')
+        assert_in(':camel:', output)
+        output = g.markdown.convert('~~~\n:camel:\n~~~')
+        assert_in('<span class="p">:</span><span class="n">camel</span><span class="p">:</span>', output)
 
     def test_markdown_commit_with_emojis(self):
         output = g.markdown_commit.convert('Thumbs up emoji :+1: wow!')
-        assert u'Thumbs up emoji \U0001F44D wow!' in output
-        output = g.markdown.convert(u'More emojis :+1::camel::three_o’clock: wow!')
-        assert u'More emojis \U0001F44D\U0001F42B\U0001F552 wow!' in output
+        assert 'Thumbs up emoji \U0001F44D wow!' in output
+        output = g.markdown.convert('More emojis :+1::camel::three_o’clock: wow!')
+        assert 'More emojis \U0001F44D\U0001F42B\U0001F552 wow!' in output
 
 class TestUserMentions(unittest.TestCase):
 
@@ -918,32 +919,32 @@ class TestIconRender(object):
         self.i = g.icons['edit']
 
     def test_default(self):
-        html = u'<a class="icon" href="#" title="Edit"><i class="fa fa-edit"></i></a>'
+        html = '<a class="icon" href="#" title="Edit"><i class="fa fa-edit"></i></a>'
         assert_equal(html, self.i.render())
 
     def test_show_title(self):
-        html = u'<a class="icon" href="#" title="Edit"><i class="fa fa-edit"></i>&nbsp;Edit</a>'
+        html = '<a class="icon" href="#" title="Edit"><i class="fa fa-edit"></i>&nbsp;Edit</a>'
         assert_equal(html, self.i.render(show_title=True))
 
-        html = u'<a class="icon" href="#" title="&lt;script&gt;"><i class="fa fa-edit"></i>&nbsp;&lt;script&gt;</a>'
+        html = '<a class="icon" href="#" title="&lt;script&gt;"><i class="fa fa-edit"></i>&nbsp;&lt;script&gt;</a>'
         assert_equal(html, self.i.render(show_title=True, title="<script>"))
 
     def test_extra_css(self):
-        html = u'<a class="icon reply btn" href="#" title="Edit"><i class="fa fa-edit"></i></a>'
+        html = '<a class="icon reply btn" href="#" title="Edit"><i class="fa fa-edit"></i></a>'
         assert_equal(html, self.i.render(extra_css='reply btn'))
 
     def test_no_closing_tag(self):
-        html = u'<a class="icon" href="#" title="Edit"><i class="fa fa-edit"></i>'
+        html = '<a class="icon" href="#" title="Edit"><i class="fa fa-edit"></i>'
         assert_equal(html, self.i.render(closing_tag=False))
 
     def test_tag(self):
-        html = u'<div class="icon" title="Edit"><i class="fa fa-edit"></i></div>'
+        html = '<div class="icon" title="Edit"><i class="fa fa-edit"></i></div>'
         assert_equal(html, self.i.render(tag='div'))
 
     def test_kwargs(self):
-        html = u'<a class="icon" data-id="123" href="#" title="Edit"><i class="fa fa-edit"></i></a>'
+        html = '<a class="icon" data-id="123" href="#" title="Edit"><i class="fa fa-edit"></i></a>'
         assert_equal(html, self.i.render(**{'data-id': '123'}))
 
     def test_escaping(self):
-        html = u'<a class="icon &#34;" data-url="&gt;" href="#" title="Edit"><i class="fa fa-edit"></i></a>'
+        html = '<a class="icon &#34;" data-url="&gt;" href="#" title="Edit"><i class="fa fa-edit"></i></a>'
         assert_equal(html, self.i.render(extra_css='"', **{'data-url': '>'}))
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index dd3e264..73f8fe4 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from unittest import TestCase
 from os import path
 from datetime import datetime, timedelta
@@ -55,7 +56,7 @@ class TestMakeSafePathPortion(TestCase):
         self.f = h.make_safe_path_portion
 
     def test_no_latin1_chars(self):
-        s = self.f(u'Задачи', relaxed=False)
+        s = self.f('Задачи', relaxed=False)
         self.assertEqual(s, '')
 
     def test_some_latin1_chars(self):
@@ -81,7 +82,7 @@ class TestMakeSafePathPortion(TestCase):
 
 def test_escape_json():
     inputdata = {"foo": "bar</script><img src=foobar onerror=alert(1)>"}
-    outputsample = '{"foo": "bar\u003C/script>\u003Cimg src=foobar onerror=alert(1)>"}'
+    outputsample = '{"foo": "bar\\u003C/script>\\u003Cimg src=foobar onerror=alert(1)>"}'
     outputdata = h.escape_json(inputdata)
     assert_equals(outputdata, outputsample)
 
@@ -89,12 +90,12 @@ def test_escape_json():
 def test_really_unicode():
     here_dir = path.dirname(__file__)
     s = h.really_unicode('\xef\xbb\xbf<?xml version="1.0" encoding="utf-8" ?>')
-    assert s.startswith(u'\ufeff')
+    assert s.startswith('\ufeff')
     s = h.really_unicode(
         open(path.join(here_dir, 'data/unicode_test.txt')).read())
     assert isinstance(s, six.text_type)
     # try non-ascii string in legacy 8bit encoding
-    h.really_unicode(u'\u0410\u0401'.encode('cp1251'))
+    h.really_unicode('\u0410\u0401'.encode('cp1251'))
     # ensure invalid encodings are handled gracefully
     s = h._attempt_encodings('foo', ['LKDJFLDK'])
     assert isinstance(s, six.text_type)
@@ -181,7 +182,7 @@ def test_context_setters():
 
 
 def test_encode_keys():
-    kw = h.encode_keys({u'foo': 5})
+    kw = h.encode_keys({'foo': 5})
     assert type(kw.keys()[0]) != six.text_type
 
 
@@ -201,8 +202,8 @@ def test_ago():
 
 def test_urlquote_unicode():
     # No exceptions please
-    h.urlquote(u'\u0410')
-    h.urlquoteplus(u'\u0410')
+    h.urlquote('\u0410')
+    h.urlquoteplus('\u0410')
 
 
 def test_sharded_path():
@@ -251,8 +252,8 @@ def test_render_any_markup_formatting():
 
 def test_render_any_markdown_encoding():
     # send encoded content in, make sure it converts it to actual unicode object which Markdown lib needs
-    assert_equals(h.render_any_markup('README.md', u'Müller'.encode('utf8')),
-                  u'<div class="markdown_content"><p>Müller</p></div>')
+    assert_equals(h.render_any_markup('README.md', 'Müller'.encode('utf8')),
+                  '<div class="markdown_content"><p>Müller</p></div>')
 
 
 class AuditLogMock(Mock):
@@ -319,7 +320,7 @@ def test_datetimeformat():
 
 def test_nl2br_jinja_filter():
     assert_equals(h.nl2br_jinja_filter('foo<script>alert(1)</script>\nbar\nbaz'),
-            Markup(u'foo&lt;script&gt;alert(1)&lt;/script&gt;<br>\nbar<br>\nbaz'))
+            Markup('foo&lt;script&gt;alert(1)&lt;/script&gt;<br>\nbar<br>\nbaz'))
 
 
 def test_split_select_field_options():
@@ -598,14 +599,14 @@ def test_base64uri_text():
 
 
 def test_slugify():
-    assert_equals(h.slugify(u'Foo Bar Bat')[0], 'Foo-Bar-Bat')
-    assert_equals(h.slugify(u'Foo_Bar')[0], 'Foo_Bar')
-    assert_equals(h.slugify(u'Foo   ')[0], 'Foo')
-    assert_equals(h.slugify(u'    Foo   ')[0], 'Foo')
-    assert_equals(h.slugify(u'"    Foo   ')[0], 'Foo')
-    assert_equals(h.slugify(u'Fôö')[0], 'Foo')
-    assert_equals(h.slugify(u'Foo.Bar')[0], 'Foo-Bar')
-    assert_equals(h.slugify(u'Foo.Bar', True)[0], 'Foo.Bar')
+    assert_equals(h.slugify('Foo Bar Bat')[0], 'Foo-Bar-Bat')
+    assert_equals(h.slugify('Foo_Bar')[0], 'Foo_Bar')
+    assert_equals(h.slugify('Foo   ')[0], 'Foo')
+    assert_equals(h.slugify('    Foo   ')[0], 'Foo')
+    assert_equals(h.slugify('"    Foo   ')[0], 'Foo')
+    assert_equals(h.slugify('Fôö')[0], 'Foo')
+    assert_equals(h.slugify('Foo.Bar')[0], 'Foo-Bar')
+    assert_equals(h.slugify('Foo.Bar', True)[0], 'Foo.Bar')
 
 
 class TestRateLimit(TestCase):
@@ -651,4 +652,4 @@ def test_hide_private_info():
 
 
 def test_emojize():
-    assert_equals(h.emojize(':smile:'), u'😄')
+    assert_equals(h.emojize(':smile:'), '😄')
diff --git a/Allura/allura/tests/test_mail_util.py b/Allura/allura/tests/test_mail_util.py
index deb16e0..eba9b8b 100644
--- a/Allura/allura/tests/test_mail_util.py
+++ b/Allura/allura/tests/test_mail_util.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import unittest
 from email.MIMEMultipart import MIMEMultipart
 from email.MIMEText import MIMEText
@@ -87,7 +88,7 @@ class TestReactor(unittest.TestCase):
 
     def test_unicode_simple_message(self):
         charset = 'utf-8'
-        msg1 = MIMEText(u'''По оживлённым берегам
+        msg1 = MIMEText('''По оживлённым берегам
 Громады стройные теснятся
 Дворцов и башен; корабли
 Толпой со всех концов земли
@@ -98,11 +99,11 @@ class TestReactor(unittest.TestCase):
         s_msg = msg1.as_string()
         msg2 = parse_message(s_msg)
         assert isinstance(msg2['payload'], six.text_type)
-        assert_in(u'всех', msg2['payload'])
+        assert_in('всех', msg2['payload'])
 
     def test_more_encodings(self):
         # these are unicode strings to reflect behavior after loading 'route_email' tasks from mongo
-        s_msg = u"""Date: Sat, 25 May 2019 09:32:00 +1000
+        s_msg = """Date: Sat, 25 May 2019 09:32:00 +1000
 From: <fo...@bar.com>
 To: <38...@bugs.proj.localhost>
 Subject: bugs
@@ -117,9 +118,9 @@ IGZ0cCx0ZWxuZXQscGluZyBjYW4ndCB3b3JrICEKCgpXaHk/
 """
         msg = parse_message(s_msg)
         assert isinstance(msg['payload'], six.text_type)
-        assert_in(u'The Snap7 application', msg['payload'])
+        assert_in('The Snap7 application', msg['payload'])
 
-        s_msg = u"""Date: Sat, 25 May 2019 09:32:00 +1000
+        s_msg = """Date: Sat, 25 May 2019 09:32:00 +1000
 From: <fo...@bar.com>
 To: <38...@bugs.proj.localhost>
 Subject: bugs
@@ -136,9 +137,9 @@ Content-Transfer-Encoding: 8bit
 """
         msg = parse_message(s_msg)
         assert isinstance(msg['payload'], six.text_type)
-        assert_in(u'• foo', msg['payload'])
+        assert_in('• foo', msg['payload'])
 
-        s_msg = u"""Date: Sat, 25 May 2019 09:32:00 +1000
+        s_msg = """Date: Sat, 25 May 2019 09:32:00 +1000
 From: <fo...@bar.com>
 To: <38...@bugs.proj.localhost>
 Subject: bugs
@@ -149,11 +150,11 @@ programmed or èrogrammed ?
 """
         msg = parse_message(s_msg)
         assert isinstance(msg['payload'], six.text_type)
-        assert_in(u'èrogrammed', msg['payload'])
+        assert_in('èrogrammed', msg['payload'])
 
     def test_more_encodings_multipart(self):
         # these are unicode strings to reflect behavior after loading 'route_email' tasks from mongo
-        s_msg = u"""Date: Sat, 25 May 2019 09:32:00 +1000
+        s_msg = """Date: Sat, 25 May 2019 09:32:00 +1000
 From: <fo...@bar.com>
 To: <38...@bugs.proj.localhost>
 Subject: bugs
@@ -180,19 +181,19 @@ Content-Type: text/html; charset="utf-8"
         msg = parse_message(s_msg)
         assert isinstance(msg['parts'][1]['payload'], six.text_type)
         assert isinstance(msg['parts'][2]['payload'], six.text_type)
-        assert_in(u'• foo', msg['parts'][1]['payload'])
-        assert_in(u'• foo', msg['parts'][2]['payload'])
+        assert_in('• foo', msg['parts'][1]['payload'])
+        assert_in('• foo', msg['parts'][2]['payload'])
 
     def test_unicode_complex_message(self):
         charset = 'utf-8'
-        p1 = MIMEText(u'''По оживлённым берегам
+        p1 = MIMEText('''По оживлённым берегам
 Громады стройные теснятся
 Дворцов и башен; корабли
 Толпой со всех концов земли
 К богатым пристаням стремятся;'''.encode(charset),
                       'plain',
                       charset)
-        p2 = MIMEText(u'''<p>По оживлённым берегам
+        p2 = MIMEText('''<p>По оживлённым берегам
 Громады стройные теснятся
 Дворцов и башен; корабли
 Толпой со всех концов земли
@@ -219,15 +220,15 @@ class TestHeader(object):
         assert_equal(str(our_header), '[asdf2:wiki] Discussion for Home page')
 
     def test_ascii(self):
-        our_header = Header(u'[asdf2:wiki] Discussion for Home page')
+        our_header = Header('[asdf2:wiki] Discussion for Home page')
         assert_equal(str(our_header), '[asdf2:wiki] Discussion for Home page')
 
     def test_utf8(self):
-        our_header = Header(u'теснятся')
+        our_header = Header('теснятся')
         assert_equal(str(our_header), '=?utf-8?b?0YLQtdGB0L3Rj9GC0YHRjw==?=')
 
     def test_name_addr(self):
-        our_header = Header(u'"теснятся"', u'<da...@b.com>')
+        our_header = Header('"теснятся"', '<da...@b.com>')
         assert_equal(str(our_header),
                      '=?utf-8?b?ItGC0LXRgdC90Y/RgtGB0Y8i?= <da...@b.com>')
 
@@ -337,6 +338,6 @@ class TestMailServer(object):
         listen_port = ('0.0.0.0', 8825)
         mailserver = MailServer(listen_port, None)
         mailserver.process_message('127.0.0.1', 'foo@bar.com', ['1234@tickets.test.p.localhost'],
-                                   u'this is the email body with headers and everything Ο'.encode('utf-8'))
+                                   'this is the email body with headers and everything Ο'.encode('utf-8'))
         assert_equal([], log.exception.call_args_list)
         log.info.assert_called_with('Msg passed along')
diff --git a/Allura/allura/tests/test_markdown.py b/Allura/allura/tests/test_markdown.py
index e122a25..10f6a52 100644
--- a/Allura/allura/tests/test_markdown.py
+++ b/Allura/allura/tests/test_markdown.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import unittest
 import mock
 
diff --git a/Allura/allura/tests/test_middlewares.py b/Allura/allura/tests/test_middlewares.py
index 58dc515..67914b0 100644
--- a/Allura/allura/tests/test_middlewares.py
+++ b/Allura/allura/tests/test_middlewares.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 ad6dbc2..34bc53f 100644
--- a/Allura/allura/tests/test_multifactor.py
+++ b/Allura/allura/tests/test_multifactor.py
@@ -14,6 +14,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 import shutil
 import tempfile
 import textwrap
@@ -95,7 +96,7 @@ class TestTotpService(object):
         time.return_value = self.sample_time
         srv = GenericTotpService()
         totp = srv.Totp(key=self.sample_key)
-        srv.verify(totp, u'283 397', None)
+        srv.verify(totp, '283 397', None)
         srv.verify(totp, b'283397', None)
 
     @patch('allura.lib.multifactor.time')
diff --git a/Allura/allura/tests/test_patches.py b/Allura/allura/tests/test_patches.py
index a1fc9bc..8c19737 100644
--- a/Allura/allura/tests/test_patches.py
+++ b/Allura/allura/tests/test_patches.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 c3ae26d..30d24e2 100644
--- a/Allura/allura/tests/test_plugin.py
+++ b/Allura/allura/tests/test_plugin.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import datetime as dt
 import calendar
 
@@ -94,16 +95,16 @@ class TestProjectRegistrationProviderParseProjectFromUrl(object):
         self.parse = self.provider.project_from_url
 
     def test_empty_url(self):
-        assert_equal((None, u'Empty url'), self.parse(None))
-        assert_equal((None, u'Empty url'), self.parse(''))
-        assert_equal((None, u'Empty url'), self.parse('/'))
+        assert_equal((None, 'Empty url'), self.parse(None))
+        assert_equal((None, 'Empty url'), self.parse(''))
+        assert_equal((None, 'Empty url'), self.parse('/'))
 
     def test_neighborhood_not_found(self):
-        assert_equal((None, u'Neighborhood not found'), self.parse('/nbhd/project'))
+        assert_equal((None, 'Neighborhood not found'), self.parse('/nbhd/project'))
 
     def test_project_not_found(self):
-        assert_equal((None, u'Project not found'), self.parse('/p/project'))
-        assert_equal((None, u'Project not found'), self.parse('project'))
+        assert_equal((None, 'Project not found'), self.parse('/p/project'))
+        assert_equal((None, 'Project not found'), self.parse('project'))
 
     def test_ok_full(self):
         p = M.Project.query.get(shortname='test')
@@ -118,7 +119,7 @@ class TestProjectRegistrationProviderParseProjectFromUrl(object):
         adobe_n = M.Neighborhood.query.get(url_prefix='/adobe/')
         M.Project(shortname='test', neighborhood_id=adobe_n._id)
         ThreadLocalORMSession.flush_all()
-        assert_equal((None, u'Too many matches for project: 2'), self.parse('test'))
+        assert_equal((None, 'Too many matches for project: 2'), self.parse('test'))
 
     def test_only_shortname_ok(self):
         p = M.Project.query.get(shortname='test')
diff --git a/Allura/allura/tests/test_scripttask.py b/Allura/allura/tests/test_scripttask.py
index 6273ee0..58b8888 100644
--- a/Allura/allura/tests/test_scripttask.py
+++ b/Allura/allura/tests/test_scripttask.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import unittest
 import mock
 
diff --git a/Allura/allura/tests/test_security.py b/Allura/allura/tests/test_security.py
index 940388c..b57ee05 100644
--- a/Allura/allura/tests/test_security.py
+++ b/Allura/allura/tests/test_security.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 6a03abb..e9c966b 100644
--- a/Allura/allura/tests/test_tasks.py
+++ b/Allura/allura/tests/test_tasks.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import operator
 import shutil
 import sys
@@ -259,9 +260,9 @@ class TestMailTasks(unittest.TestCase):
             mail_tasks.sendmail(
                 fromaddr=str(c.user._id),
                 destinations=[str(c.user._id)],
-                text=u'This is a test',
+                text='This is a test',
                 reply_to=g.noreply,
-                subject=u'Test subject',
+                subject='Test subject',
                 message_id=h.gen_message_id())
             assert_equal(_client.sendmail.call_count, 1)
             return_path, rcpts, body = _client.sendmail.call_args[0]
@@ -280,11 +281,11 @@ class TestMailTasks(unittest.TestCase):
     def test_send_email_nonascii(self):
         with mock.patch.object(mail_tasks.smtp_client, '_client') as _client:
             mail_tasks.sendmail(
-                fromaddr=u'"По" <fo...@bar.com>',
+                fromaddr='"По" <fo...@bar.com>',
                 destinations=['blah@blah.com'],
-                text=u'Громады стройные теснятся',
+                text='Громады стройные теснятся',
                 reply_to=g.noreply,
-                subject=u'По оживлённым берегам',
+                subject='По оживлённым берегам',
                 message_id=h.gen_message_id())
             assert_equal(_client.sendmail.call_count, 1)
             return_path, rcpts, body = _client.sendmail.call_args[0]
@@ -303,7 +304,7 @@ class TestMailTasks(unittest.TestCase):
             assert_in('Content-Type: text/plain; charset="utf-8"', body)
             assert_in('Content-Transfer-Encoding: base64', body)
             assert_in(
-                b64encode(u'Громады стройные теснятся'.encode('utf-8')), body)
+                b64encode('Громады стройные теснятся'.encode('utf-8')), body)
 
     def test_send_email_with_disabled_user(self):
         c.user = M.User.by_username('test-admin')
@@ -315,9 +316,9 @@ class TestMailTasks(unittest.TestCase):
             mail_tasks.sendmail(
                 fromaddr=str(c.user._id),
                 destinations=[str(destination_user._id)],
-                text=u'This is a test',
+                text='This is a test',
                 reply_to=g.noreply,
-                subject=u'Test subject',
+                subject='Test subject',
                 message_id=h.gen_message_id())
             assert_equal(_client.sendmail.call_count, 1)
             return_path, rcpts, body = _client.sendmail.call_args[0]
@@ -334,9 +335,9 @@ class TestMailTasks(unittest.TestCase):
             mail_tasks.sendmail(
                 fromaddr=str(c.user._id),
                 destinations=[str(destination_user._id)],
-                text=u'This is a test',
+                text='This is a test',
                 reply_to=g.noreply,
-                subject=u'Test subject',
+                subject='Test subject',
                 message_id=h.gen_message_id())
             assert_equal(_client.sendmail.call_count, 0)
 
@@ -346,9 +347,9 @@ class TestMailTasks(unittest.TestCase):
             mail_tasks.sendsimplemail(
                 fromaddr=str(c.user._id),
                 toaddr='test@mail.com',
-                text=u'This is a test',
+                text='This is a test',
                 reply_to=g.noreply,
-                subject=u'Test subject',
+                subject='Test subject',
                 message_id=h.gen_message_id())
             assert_equal(_client.sendmail.call_count, 1)
             return_path, rcpts, body = _client.sendmail.call_args[0]
@@ -360,9 +361,9 @@ class TestMailTasks(unittest.TestCase):
             mail_tasks.sendsimplemail(
                 fromaddr=str(c.user._id),
                 toaddr='test@mail.com',
-                text=u'This is a test',
+                text='This is a test',
                 reply_to=g.noreply,
-                subject=u'Test subject',
+                subject='Test subject',
                 message_id=h.gen_message_id())
             assert_equal(_client.sendmail.call_count, 2)
             return_path, rcpts, body = _client.sendmail.call_args[0]
@@ -375,10 +376,10 @@ class TestMailTasks(unittest.TestCase):
             mail_tasks.sendsimplemail(
                 fromaddr=str(c.user._id),
                 toaddr='test@mail.com',
-                text=u'This is a test',
+                text='This is a test',
                 reply_to=g.noreply,
-                subject=u'Test subject',
-                sender=u'tickets@test.p.domain.net',
+                subject='Test subject',
+                sender='tickets@test.p.domain.net',
                 message_id=h.gen_message_id())
             assert_equal(_client.sendmail.call_count, 1)
             return_path, rcpts, body = _client.sendmail.call_args[0]
@@ -391,10 +392,10 @@ class TestMailTasks(unittest.TestCase):
             mail_tasks.sendmail(
                 fromaddr=str(c.user._id),
                 destinations=[str(c.user._id)],
-                text=u'This is a test',
-                reply_to=u'123@tickets.test.p.domain.net',
-                subject=u'Test subject',
-                sender=u'tickets@test.p.domain.net',
+                text='This is a test',
+                reply_to='123@tickets.test.p.domain.net',
+                subject='Test subject',
+                sender='tickets@test.p.domain.net',
                 message_id=h.gen_message_id())
             assert_equal(_client.sendmail.call_count, 1)
             return_path, rcpts, body = _client.sendmail.call_args[0]
@@ -409,9 +410,9 @@ class TestMailTasks(unittest.TestCase):
             mail_tasks.sendsimplemail(
                 fromaddr=str(c.user._id),
                 toaddr='test@mail.com',
-                text=u'This is a test',
+                text='This is a test',
                 reply_to=g.noreply,
-                subject=u'Test subject',
+                subject='Test subject',
                 references=['a', 'b', 'c'],
                 message_id=h.gen_message_id())
             assert_equal(_client.sendmail.call_count, 1)
@@ -424,10 +425,10 @@ class TestMailTasks(unittest.TestCase):
             mail_tasks.sendmail(
                 fromaddr=str(c.user._id),
                 destinations=[str(c.user._id)],
-                text=u'This is a test',
+                text='This is a test',
                 reply_to=g.noreply,
-                subject=u'Test subject',
-                references=u'ref',
+                subject='Test subject',
+                references='ref',
                 message_id=h.gen_message_id())
             assert_equal(_client.sendmail.call_count, 1)
             return_path, rcpts, body = _client.sendmail.call_args[0]
@@ -441,10 +442,10 @@ class TestMailTasks(unittest.TestCase):
             mail_tasks.sendsimplemail(
                 fromaddr=str(c.user._id),
                 toaddr='test@mail.com',
-                text=u'This is a test',
+                text='This is a test',
                 reply_to=g.noreply,
-                subject=u'Test subject',
-                cc=u'someone@example.com',
+                subject='Test subject',
+                cc='someone@example.com',
                 message_id=h.gen_message_id())
             assert_equal(_client.sendmail.call_count, 1)
             return_path, rcpts, body = _client.sendmail.call_args[0]
@@ -457,9 +458,9 @@ class TestMailTasks(unittest.TestCase):
             mail_tasks.sendsimplemail(
                 fromaddr=c.user._id,
                 toaddr='test@mail.com',
-                text=u'This is a test',
+                text='This is a test',
                 reply_to=g.noreply,
-                subject=u'Test subject',
+                subject='Test subject',
                 message_id=h.gen_message_id())
             assert_equal(_client.sendmail.call_count, 1)
             return_path, rcpts, body = _client.sendmail.call_args[0]
@@ -468,11 +469,11 @@ class TestMailTasks(unittest.TestCase):
     def test_send_email_long_lines_use_quoted_printable(self):
         with mock.patch.object(mail_tasks.smtp_client, '_client') as _client:
             mail_tasks.sendsimplemail(
-                fromaddr=u'"По" <fo...@bar.com>',
+                fromaddr='"По" <fo...@bar.com>',
                 toaddr='blah@blah.com',
-                text=(u'0123456789' * 100) + u'\n\n' + (u'Громады стро ' * 100),
+                text=('0123456789' * 100) + '\n\n' + ('Громады стро ' * 100),
                 reply_to=g.noreply,
-                subject=u'По оживлённым берегам',
+                subject='По оживлённым берегам',
                 message_id=h.gen_message_id())
             return_path, rcpts, body = _client.sendmail.call_args[0]
             body = body.split('\n')
@@ -642,7 +643,7 @@ class TestExportTasks(unittest.TestCase):
     @td.with_wiki
     def test_bulk_export(self, wiki_bulk_export, zipdir, shutil):
         M.MonQTask.query.remove()
-        export_tasks.bulk_export([u'wiki'])
+        export_tasks.bulk_export(['wiki'])
         assert_equal(wiki_bulk_export.call_count, 1)
         temp = '/tmp/bulk_export/p/test/test'
         zipfn = '/tmp/bulk_export/p/test/test.zip'
diff --git a/Allura/allura/tests/test_utils.py b/Allura/allura/tests/test_utils.py
index 12017e2..feaf059 100644
--- a/Allura/allura/tests/test_utils.py
+++ b/Allura/allura/tests/test_utils.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import json
 import time
 import unittest
@@ -342,7 +343,7 @@ def test_empty_cursor():
 
 
 def test_DateJSONEncoder():
-    data = {'message': u'Hi!',
+    data = {'message': 'Hi!',
             'date': dt.datetime(2015, 01, 30, 13, 13, 13)}
     result = json.dumps(data, cls=utils.DateJSONEncoder)
     assert_equal(result, '{"date": "2015-01-30T13:13:13Z", "message": "Hi!"}')
@@ -373,7 +374,7 @@ class FakeAttachment(object):
         self._id = ObjectId()
         self.filename = filename
     def __repr__(self):
-        return u'%s %s' % (self._id, self.filename)
+        return '%s %s' % (self._id, self.filename)
 
 
 def unique_attachments():
@@ -417,13 +418,13 @@ def test_lsub_utf8():
     assert_equal(b'asdf',
                  utils.lsub_utf8(h.really_unicode('asdf').encode('utf-8'), 40))
     assert_equal(b'as\xf0\x9f\x98\x84\xc2\xb6\xc2\xba\xc2\xb6',
-                 utils.lsub_utf8(h.really_unicode(u'as😄¶º¶').encode('utf-8'), 40))
+                 utils.lsub_utf8(h.really_unicode('as😄¶º¶').encode('utf-8'), 40))
     assert_equal(b'as\xf0\x9f\x98\x84',
-                 utils.lsub_utf8(h.really_unicode(u'as😄¶º¶').encode('utf-8'), 6))
+                 utils.lsub_utf8(h.really_unicode('as😄¶º¶').encode('utf-8'), 6))
     # these would truncate the smiley:
     assert_equal(b'as',
-                 utils.lsub_utf8(h.really_unicode(u'as😄¶º¶').encode('utf-8'), 5))
+                 utils.lsub_utf8(h.really_unicode('as😄¶º¶').encode('utf-8'), 5))
     assert_equal(b'as',
-                 utils.lsub_utf8(h.really_unicode(u'as😄¶º¶').encode('utf-8'), 4))
+                 utils.lsub_utf8(h.really_unicode('as😄¶º¶').encode('utf-8'), 4))
     assert_equal(b'as',
-                 utils.lsub_utf8(h.really_unicode(u'as😄¶º¶').encode('utf-8'), 3))
+                 utils.lsub_utf8(h.really_unicode('as😄¶º¶').encode('utf-8'), 3))
diff --git a/Allura/allura/tests/test_validators.py b/Allura/allura/tests/test_validators.py
index f482efb..3f9d27a 100644
--- a/Allura/allura/tests/test_validators.py
+++ b/Allura/allura/tests/test_validators.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 60853be..a1fad06 100644
--- a/Allura/allura/tests/test_webhooks.py
+++ b/Allura/allura/tests/test_webhooks.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import json
 import hmac
 import hashlib
@@ -99,10 +100,10 @@ class TestValidators(TestWebhookBase):
         v = WebhookValidator(sender=sender, app=app, not_empty=True)
         with assert_raises(Invalid) as cm:
             v.to_python(None)
-        assert_equal(cm.exception.msg, u'Please enter a value')
+        assert_equal(cm.exception.msg, 'Please enter a value')
         with assert_raises(Invalid) as cm:
             v.to_python('invalid id')
-        assert_equal(cm.exception.msg, u'Invalid webhook')
+        assert_equal(cm.exception.msg, 'Invalid webhook')
 
         wh = M.Webhook(type='invalid type',
                        app_config_id=invalid_app.config._id,
@@ -112,14 +113,14 @@ class TestValidators(TestWebhookBase):
         # invalid type
         with assert_raises(Invalid) as cm:
             v.to_python(wh._id)
-        assert_equal(cm.exception.msg, u'Invalid webhook')
+        assert_equal(cm.exception.msg, 'Invalid webhook')
 
         wh.type = 'repo-push'
         session(wh).flush(wh)
         # invalild app
         with assert_raises(Invalid) as cm:
             v.to_python(wh._id)
-        assert_equal(cm.exception.msg, u'Invalid webhook')
+        assert_equal(cm.exception.msg, 'Invalid webhook')
 
         wh.app_config_id = app.config._id
         session(wh).flush(wh)
@@ -198,7 +199,7 @@ class TestWebhookController(TestController):
         r = self.app.get(self.url)
         assert_in('<h1>repo-push</h1>', r)
         assert_not_in('http://httpbin.org/post', r)
-        data = {'url': u'http://httpbin.org/post',
+        data = {'url': 'http://httpbin.org/post',
                 'secret': ''}
         msg = 'add webhook repo-push {} {}'.format(
             data['url'], self.git.config.url())
@@ -224,7 +225,7 @@ class TestWebhookController(TestController):
         assert_equal(M.Webhook.query.find().count(), 0)
         limit = json.dumps({'git': 1})
         with h.push_config(config, **{'webhook.repo_push.max_hooks': limit}):
-            data = {'url': u'http://httpbin.org/post',
+            data = {'url': 'http://httpbin.org/post',
                     'secret': ''}
             r = self.create_webhook(data).follow()
             assert_equal(M.Webhook.query.find().count(), 1)
@@ -264,10 +265,10 @@ class TestWebhookController(TestController):
 
         Maybe something to do with WebhookControllerMeta setup of `validate` decorators?
         """
-        data1 = {'url': u'http://httpbin.org/post',
-                 'secret': u'secret'}
-        data2 = {'url': u'http://example.com/hook',
-                 'secret': u'secret2'}
+        data1 = {'url': 'http://httpbin.org/post',
+                 'secret': 'secret'}
+        data2 = {'url': 'http://example.com/hook',
+                 'secret': 'secret2'}
         self.create_webhook(data1).follow()
         self.create_webhook(data2).follow()
         assert_equal(M.Webhook.query.find().count(), 2)
@@ -299,7 +300,7 @@ class TestWebhookController(TestController):
         form['url'] = data2['url']
         r = form.submit()
         self.find_error(r, '_the_form',
-                        u'"repo-push" webhook already exists for Git http://example.com/hook',
+                        '"repo-push" webhook already exists for Git http://example.com/hook',
                         form_type='edit')
 
     def test_edit_validation(self):
@@ -311,8 +312,8 @@ class TestWebhookController(TestController):
         session(invalid).flush(invalid)
         self.app.get(self.url + '/repo-push/%s' % invalid._id, status=404)
 
-        data = {'url': u'http://httpbin.org/post',
-                'secret': u'secret'}
+        data = {'url': 'http://httpbin.org/post',
+                'secret': 'secret'}
         self.create_webhook(data).follow()
         wh = M.Webhook.query.get(hook_url=data['url'], type='repo-push')
 
@@ -333,8 +334,8 @@ class TestWebhookController(TestController):
                         'You must provide a full domain name (like qwe.com)', 'edit')
 
     def test_delete(self):
-        data = {'url': u'http://httpbin.org/post',
-                'secret': u'secret'}
+        data = {'url': 'http://httpbin.org/post',
+                'secret': 'secret'}
         self.create_webhook(data).follow()
         assert_equal(M.Webhook.query.find().count(), 1)
         wh = M.Webhook.query.get(hook_url=data['url'])
@@ -366,11 +367,11 @@ class TestWebhookController(TestController):
     def test_list_webhooks(self):
         git2 = self.project.app_instance('src2')
         url2 = str(git2.admin_url + 'webhooks')
-        data1 = {'url': u'http://httpbin.org/post',
+        data1 = {'url': 'http://httpbin.org/post',
                  'secret': 'secret'}
-        data2 = {'url': u'http://another-host.org/',
+        data2 = {'url': 'http://another-host.org/',
                  'secret': 'secret2'}
-        data3 = {'url': u'http://another-app.org/',
+        data3 = {'url': 'http://another-app.org/',
                  'secret': 'secret3'}
         self.create_webhook(data1).follow()
         self.create_webhook(data2).follow()
@@ -387,20 +388,20 @@ class TestWebhookController(TestController):
             [{'text': wh1.hook_url},
              {'text': wh1.secret},
              {'href': self.url + '/repo-push/' + str(wh1._id),
-              'text': u'Edit'},
+              'text': 'Edit'},
              {'href': self.url + '/repo-push/delete',
               'data-id': str(wh1._id)}],
             [{'text': wh2.hook_url},
              {'text': wh2.secret},
              {'href': self.url + '/repo-push/' + str(wh2._id),
-              'text': u'Edit'},
+              'text': 'Edit'},
              {'href': self.url + '/repo-push/delete',
               'data-id': str(wh2._id)}],
         ])
         assert_equal(rows, expected_rows)
         # make sure webhooks for another app is not visible
-        assert_not_in(u'http://another-app.org/', r)
-        assert_not_in(u'secret3', r)
+        assert_not_in('http://another-app.org/', r)
+        assert_not_in('secret3', r)
 
     def _format_row(self, row):
         def link(td):
@@ -575,13 +576,13 @@ class TestRepoPushWebhookSender(TestWebhookBase):
         expected_result = {
             'size': 3,
             'commits': [{'id': '1'}, {'id': '2'}, {'id': '3'}],
-            'ref': u'ref',
-            'after': u'1',
-            'before': u'0',
+            'ref': 'ref',
+            'after': '1',
+            'before': '0',
             'repository': {
-                'full_name': u'/adobe/adobe-1/src/',
-                'name': u'Git',
-                'url': u'http://localhost/adobe/adobe-1/src/',
+                'full_name': '/adobe/adobe-1/src/',
+                'name': 'Git',
+                'url': 'http://localhost/adobe/adobe-1/src/',
             },
         }
         assert_equal(result, expected_result)
@@ -660,10 +661,10 @@ class TestModels(TestWebhookBase):
     def test_json(self):
         expected = {
             '_id': six.text_type(self.wh._id),
-            'url': u'http://localhost/rest/adobe/adobe-1/admin'
-                   u'/src/webhooks/repo-push/{}'.format(self.wh._id),
-            'type': u'repo-push',
-            'hook_url': u'http://httpbin.org/post',
+            'url': 'http://localhost/rest/adobe/adobe-1/admin'
+                   '/src/webhooks/repo-push/{}'.format(self.wh._id),
+            'type': 'repo-push',
+            'hook_url': 'http://httpbin.org/post',
             'mod_date': self.wh.mod_date,
         }
         dd.assert_equal(self.wh.__json__(), expected)
@@ -748,17 +749,17 @@ class TestWebhookRestController(TestRestApiBase):
 
         r = self.api_post(self.url + '/repo-push', status=400)
         expected = {
-            u'result': u'error',
-            u'error': {u'url': u'Please enter a value'},
+            'result': 'error',
+            'error': {'url': 'Please enter a value'},
         }
         assert_equal(r.json, expected)
 
         data = {'url': 'qwer', 'secret': 'qwe'}
         r = self.api_post(self.url + '/repo-push', status=400, **data)
         expected = {
-            u'result': u'error',
-            u'error': {
-                u'url': u'You must provide a full domain name (like qwer.com)'
+            'result': 'error',
+            'error': {
+                'url': 'You must provide a full domain name (like qwer.com)'
             },
         }
         assert_equal(r.json, expected)
@@ -766,7 +767,7 @@ class TestWebhookRestController(TestRestApiBase):
 
     def test_create(self):
         assert_equal(M.Webhook.query.find().count(), len(self.webhooks))
-        data = {u'url': u'http://hook.slack.com/abcd'}
+        data = {'url': 'http://hook.slack.com/abcd'}
         limit = json.dumps({'git': 10})
         with h.push_config(config, **{'webhook.repo_push.max_hooks': limit}):
             msg = 'add webhook repo-push {} {}'.format(
@@ -788,37 +789,37 @@ class TestWebhookRestController(TestRestApiBase):
 
     def test_create_duplicates(self):
         assert_equal(M.Webhook.query.find().count(), len(self.webhooks))
-        data = {u'url': self.webhooks[0].hook_url}
+        data = {'url': self.webhooks[0].hook_url}
         limit = json.dumps({'git': 10})
         with h.push_config(config, **{'webhook.repo_push.max_hooks': limit}):
             r = self.api_post(self.url + '/repo-push', status=400, **data)
-        expected = {u'result': u'error',
-                    u'error': u'_the_form: "repo-push" webhook already '
-                              u'exists for Git http://httpbin.org/post/0'}
+        expected = {'result': 'error',
+                    'error': '_the_form: "repo-push" webhook already '
+                              'exists for Git http://httpbin.org/post/0'}
         assert_equal(r.json, expected)
         assert_equal(M.Webhook.query.find().count(), len(self.webhooks))
 
     def test_create_limit_reached(self):
         assert_equal(M.Webhook.query.find().count(), len(self.webhooks))
-        data = {u'url': u'http://hook.slack.com/abcd'}
+        data = {'url': 'http://hook.slack.com/abcd'}
         r = self.api_post(self.url + '/repo-push', status=400, **data)
         expected = {
-            u'result': u'error',
-            u'limits': {u'max': 3, u'used': 3},
-            u'error': u'You have exceeded the maximum number of webhooks '
-                      u'you are allowed to create for this project/app'}
+            'result': 'error',
+            'limits': {'max': 3, 'used': 3},
+            'error': 'You have exceeded the maximum number of webhooks '
+                      'you are allowed to create for this project/app'}
         assert_equal(r.json, expected)
         assert_equal(M.Webhook.query.find().count(), len(self.webhooks))
 
     def test_edit_validation(self):
         webhook = self.webhooks[0]
-        url = u'{}/repo-push/{}'.format(self.url, webhook._id)
+        url = '{}/repo-push/{}'.format(self.url, webhook._id)
         data = {'url': 'qwe', 'secret': 'qwe'}
         r = self.api_post(url, status=400, **data)
         expected = {
-            u'result': u'error',
-            u'error': {
-                u'url': u'You must provide a full domain name (like qwe.com)'
+            'result': 'error',
+            'error': {
+                'url': 'You must provide a full domain name (like qwe.com)'
             },
         }
         assert_equal(r.json, expected)
@@ -870,9 +871,9 @@ class TestWebhookRestController(TestRestApiBase):
         url = '{}/repo-push/{}'.format(self.url, webhook._id)
         data = {'url': 'http://httpbin.org/post/1'}
         r = self.api_post(url, status=400, **data)
-        expected = {u'result': u'error',
-                    u'error': u'_the_form: "repo-push" webhook already '
-                              u'exists for Git http://httpbin.org/post/1'}
+        expected = {'result': 'error',
+                    'error': '_the_form: "repo-push" webhook already '
+                              'exists for Git http://httpbin.org/post/1'}
         assert_equal(r.json, expected)
 
     def test_delete_validation(self):
@@ -887,7 +888,7 @@ class TestWebhookRestController(TestRestApiBase):
             webhook.hook_url, self.git.config.url())
         with td.audits(msg):
             r = self.api_delete(url, status=200)
-        dd.assert_equal(r.json, {u'result': u'ok'})
+        dd.assert_equal(r.json, {'result': 'ok'})
         assert_equal(M.Webhook.query.find().count(), 2)
         assert_equal(M.Webhook.query.get(_id=webhook._id), None)
 
diff --git a/Allura/allura/tests/tscript.py b/Allura/allura/tests/tscript.py
index 6691331..022a710 100644
--- a/Allura/allura/tests/tscript.py
+++ b/Allura/allura/tests/tscript.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 
 from allura import model as M
diff --git a/Allura/allura/tests/tscript_error.py b/Allura/allura/tests/tscript_error.py
index ddba357..6006b88 100644
--- a/Allura/allura/tests/tscript_error.py
+++ b/Allura/allura/tests/tscript_error.py
@@ -16,4 +16,5 @@
 #       under the License.
 
 '''Script that raises ValueError'''
+from __future__ import unicode_literals
 raise ValueError
diff --git a/Allura/allura/tests/unit/controllers/test_auth.py b/Allura/allura/tests/unit/controllers/test_auth.py
index 8fb8e46..6b83d2d 100644
--- a/Allura/allura/tests/unit/controllers/test_auth.py
+++ b/Allura/allura/tests/unit/controllers/test_auth.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 
+from __future__ import unicode_literals
 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 e6d0353..7141df8 100644
--- a/Allura/allura/tests/unit/controllers/test_discussion_moderation_controller.py
+++ b/Allura/allura/tests/unit/controllers/test_discussion_moderation_controller.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 20f3eb8..48df41d 100644
--- a/Allura/allura/tests/unit/controllers/test_dispatch_index.py
+++ b/Allura/allura/tests/unit/controllers/test_dispatch_index.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 6acb54f..6e66e4e 100644
--- a/Allura/allura/tests/unit/factories.py
+++ b/Allura/allura/tests/unit/factories.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 eaa6404..700f1e0 100644
--- a/Allura/allura/tests/unit/patches.py
+++ b/Allura/allura/tests/unit/patches.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 cf0d5cf..9f4a165 100644
--- a/Allura/allura/tests/unit/phone/test_nexmo.py
+++ b/Allura/allura/tests/unit/phone/test_nexmo.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 aa6bd51..7039285 100644
--- a/Allura/allura/tests/unit/phone/test_phone_service.py
+++ b/Allura/allura/tests/unit/phone/test_phone_service.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 f089303..b8a0315 100644
--- a/Allura/allura/tests/unit/spam/test_akismet.py
+++ b/Allura/allura/tests/unit/spam/test_akismet.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 
+from __future__ import unicode_literals
 import mock
 import unittest
 import urllib
@@ -56,13 +57,13 @@ class TestAkismet(unittest.TestCase):
                 )
             ),
         })
-        self.fake_user = mock.Mock(display_name=u'Søme User',
+        self.fake_user = mock.Mock(display_name='Søme User',
                                    email_addresses=['user@domain'],
                                    _id=ObjectId())
         self.fake_headers = dict(
             USER_AGENT='some browser',
             REFERER='some url')
-        self.content = u'spåm text'
+        self.content = 'spåm text'
         self.expected_data = dict(
             comment_content=self.content.encode('utf8'),
             comment_type='comment',
@@ -111,7 +112,7 @@ class TestAkismet(unittest.TestCase):
         c.user = None
         self.akismet.check(self.content, user=self.fake_user)
         expected_data = self.expected_data
-        expected_data.update(comment_author=u'Søme User'.encode('utf8'),
+        expected_data.update(comment_author='Søme User'.encode('utf8'),
                              comment_author_email='user@domain')
         self.akismet.service.comment_check.assert_called_once_with(**expected_data)
 
@@ -123,7 +124,7 @@ class TestAkismet(unittest.TestCase):
         c.user = self.fake_user
         self.akismet.check(self.content)
         expected_data = self.expected_data
-        expected_data.update(comment_author=u'Søme User'.encode('utf8'),
+        expected_data.update(comment_author='Søme User'.encode('utf8'),
                              comment_author_email='user@domain')
         self.akismet.service.comment_check.assert_called_once_with(**expected_data)
 
@@ -134,7 +135,7 @@ class TestAkismet(unittest.TestCase):
         self.akismet.submit_spam(self.content)
 
         # no IP addr, UA, etc, since this isn't the original request
-        expected_data = dict(comment_content=u'spåm text'.encode('utf8'),
+        expected_data = dict(comment_content='spåm text'.encode('utf8'),
                              comment_type='comment',
                              user_ip='',
                              user_agent='',
@@ -148,7 +149,7 @@ class TestAkismet(unittest.TestCase):
         self.akismet.submit_ham(self.content)
 
         # no IP addr, UA, etc, since this isn't the original request
-        expected_data = dict(comment_content=u'spåm text'.encode('utf8'),
+        expected_data = dict(comment_content='spåm text'.encode('utf8'),
                              comment_type='comment',
                              user_ip='',
                              user_agent='',
@@ -161,7 +162,7 @@ class TestAkismet(unittest.TestCase):
 
         self.akismet.submit_ham(self.content, artifact=self.fake_artifact)
 
-        expected_data = dict(comment_content=u'spåm text'.encode('utf8'),
+        expected_data = dict(comment_content='spåm text'.encode('utf8'),
                              comment_type='comment',
                              user_ip='33.4.5.66',
                              user_agent='',
diff --git a/Allura/allura/tests/unit/spam/test_spam_filter.py b/Allura/allura/tests/unit/spam/test_spam_filter.py
index 607273d..2770121 100644
--- a/Allura/allura/tests/unit/spam/test_spam_filter.py
+++ b/Allura/allura/tests/unit/spam/test_spam_filter.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 77f0e89..b0d15f8 100644
--- a/Allura/allura/tests/unit/spam/test_stopforumspam.py
+++ b/Allura/allura/tests/unit/spam/test_stopforumspam.py
@@ -16,6 +16,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 import tempfile
 
 import mock
@@ -29,7 +30,7 @@ from allura.lib.spam.stopforumspamfilter import StopForumSpamSpamFilter
 class TestStopForumSpam(object):
 
     def setUp(self):
-        self.content = u'spåm text'
+        self.content = 'spåm text'
 
         self.artifact = mock.Mock()
         self.artifact.project_id = ObjectId()
diff --git a/Allura/allura/tests/unit/test_app.py b/Allura/allura/tests/unit/test_app.py
index 667dc09..719f125 100644
--- a/Allura/allura/tests/unit/test_app.py
+++ b/Allura/allura/tests/unit/test_app.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 895eb74..1337b38 100644
--- a/Allura/allura/tests/unit/test_artifact.py
+++ b/Allura/allura/tests/unit/test_artifact.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 07c9525..665240f 100644
--- a/Allura/allura/tests/unit/test_discuss.py
+++ b/Allura/allura/tests/unit/test_discuss.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 039bb00..f89c6aa 100644
--- a/Allura/allura/tests/unit/test_helpers/test_ago.py
+++ b/Allura/allura/tests/unit/test_helpers/test_ago.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 89e5977..ba29a32 100644
--- a/Allura/allura/tests/unit/test_helpers/test_set_context.py
+++ b/Allura/allura/tests/unit/test_helpers/test_set_context.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 c131be4..1500252 100644
--- a/Allura/allura/tests/unit/test_ldap_auth_provider.py
+++ b/Allura/allura/tests/unit/test_ldap_auth_provider.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import calendar
 import platform
 from datetime import datetime, timedelta
@@ -98,21 +99,21 @@ class TestLdapAuthenticationProvider(object):
         ldap.dn.escape_dn_chars = lambda x: x
         dn = 'uid=%s,ou=people,dc=localdomain' % params['username']
         conn = ldap.initialize.return_value
-        conn.search_s.return_value = [(dn, {'cn': [u'åℒƒ'.encode('utf-8')]})]
+        conn.search_s.return_value = [(dn, {'cn': ['åℒƒ'.encode('utf-8')]})]
 
         self.provider._login()
 
         user = M.User.query.get(username=params['username'])
         assert user
-        assert_equal(user.display_name, u'åℒƒ')
+        assert_equal(user.display_name, 'åℒƒ')
 
     @patch('allura.lib.plugin.modlist')
     @patch('allura.lib.plugin.ldap')
     def test_register_user(self, ldap, modlist):
         user_doc = {
-            'username': u'new-user',
-            'display_name': u'New User',
-            'password': u'new-password',
+            'username': 'new-user',
+            'display_name': 'New User',
+            'password': 'new-password',
         }
         ldap.dn.escape_dn_chars = lambda x: x
         self.provider._encode_password = Mock(return_value='new-password-hash')
diff --git a/Allura/allura/tests/unit/test_mixins.py b/Allura/allura/tests/unit/test_mixins.py
index cdc3aaa..a29d013 100644
--- a/Allura/allura/tests/unit/test_mixins.py
+++ b/Allura/allura/tests/unit/test_mixins.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 781ec83..2422aab 100644
--- a/Allura/allura/tests/unit/test_package_path_loader.py
+++ b/Allura/allura/tests/unit/test_package_path_loader.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 2f9a4d3..031168a 100644
--- a/Allura/allura/tests/unit/test_post_model.py
+++ b/Allura/allura/tests/unit/test_post_model.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 28ba7fa..4eaef6c 100644
--- a/Allura/allura/tests/unit/test_project.py
+++ b/Allura/allura/tests/unit/test_project.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import unittest
 from mock import Mock
 
@@ -40,10 +41,10 @@ class TestProject(unittest.TestCase):
         p.sitemap = Mock(return_value=sitemap_entries)
         entries = p.grouped_navbar_entries()
         expected = [
-            (u'Tickets \u25be', 'proj_url/_list/tickets', 3),
-            (u'wiki', 'wiki url', 0),
-            (u'Discussion \u25be', 'proj_url/_list/discussion', 2),
-            (u'subproject', 'subproject url', 0),
+            ('Tickets \u25be', 'proj_url/_list/tickets', 3),
+            ('wiki', 'wiki url', 0),
+            ('Discussion \u25be', 'proj_url/_list/discussion', 2),
+            ('subproject', 'subproject url', 0),
         ]
         expected_ticket_urls = ['bugs url', 'features url', 'support url']
         actual = [(e.label, e.url, len(e.matching_urls)) for e in entries]
@@ -67,11 +68,11 @@ class TestProject(unittest.TestCase):
         p.tool_data['allura'] = {'grouping_threshold': 2}
         entries = p.grouped_navbar_entries()
         expected = [
-            (u'Tickets \u25be', 'proj_url/_list/tickets', 3),
-            (u'wiki', 'wiki url', 0),
-            (u'discuss', 'discuss url', 0),
-            (u'subproject', 'subproject url', 0),
-            (u'help', 'help url', 0),
+            ('Tickets \u25be', 'proj_url/_list/tickets', 3),
+            ('wiki', 'wiki url', 0),
+            ('discuss', 'discuss url', 0),
+            ('subproject', 'subproject url', 0),
+            ('help', 'help url', 0),
         ]
         expected_ticket_urls = ['bugs url', 'features url', 'support url']
         actual = [(e.label, e.url, len(e.matching_urls)) for e in entries]
diff --git a/Allura/allura/tests/unit/test_repo.py b/Allura/allura/tests/unit/test_repo.py
index 786d413..1e20c59 100644
--- a/Allura/allura/tests/unit/test_repo.py
+++ b/Allura/allura/tests/unit/test_repo.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import datetime
 import unittest
 from mock import patch, Mock, MagicMock, call
diff --git a/Allura/allura/tests/unit/test_session.py b/Allura/allura/tests/unit/test_session.py
index dc9711d..3d8ce08 100644
--- a/Allura/allura/tests/unit/test_session.py
+++ b/Allura/allura/tests/unit/test_session.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import pymongo
 import mock
 
diff --git a/Allura/allura/tests/unit/test_sitemapentry.py b/Allura/allura/tests/unit/test_sitemapentry.py
index bdd6399..af294f5 100644
--- a/Allura/allura/tests/unit/test_sitemapentry.py
+++ b/Allura/allura/tests/unit/test_sitemapentry.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 5ef3492..e1fdcf0 100644
--- a/Allura/allura/tests/unit/test_solr.py
+++ b/Allura/allura/tests/unit/test_solr.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import unittest
 
 import mock
diff --git a/Allura/allura/version.py b/Allura/allura/version.py
index e880449..10bcc51 100644
--- a/Allura/allura/version.py
+++ b/Allura/allura/version.py
@@ -15,5 +15,6 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 __version_info__ = (0, 1)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/Allura/allura/webhooks.py b/Allura/allura/webhooks.py
index d07268d..ca46755 100644
--- a/Allura/allura/webhooks.py
+++ b/Allura/allura/webhooks.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import json
 import hmac
@@ -66,7 +67,7 @@ class WebhookValidator(fev.FancyValidator):
                 pass
         if wh and wh.type == self.sender.type and wh.app_config_id == self.app.config._id:
             return wh
-        raise Invalid(u'Invalid webhook', value, state)
+        raise Invalid('Invalid webhook', value, state)
 
 
 class WebhookCreateForm(schema.Schema):
@@ -121,7 +122,7 @@ class WebhookController(BaseController, AdminControllerMixin):
             session(wh).flush(wh)
         except DuplicateKeyError:
             session(wh).expunge(wh)
-            msg = u'_the_form: "{}" webhook already exists for {} {}'.format(
+            msg = '_the_form: "{}" webhook already exists for {} {}'.format(
                 wh.type, self.app.config.options.mount_label, url)
             raise Invalid(msg, None, None)
 
@@ -470,16 +471,16 @@ class RepoPushWebhookSender(WebhookSender):
                 # Merge commit will have multiple parents. As far as I can tell
                 # the last one will be the branch head before merge
                 return self._convert_id(parents[-1])
-        return u''
+        return ''
 
     def _after(self, commit_ids):
         if len(commit_ids) > 0:
             return self._convert_id(commit_ids[0])
-        return u''
+        return ''
 
     def _convert_id(self, _id):
         if ':' in _id:
-            _id = u'r' + _id.rsplit(':', 1)[1]
+            _id = 'r' + _id.rsplit(':', 1)[1]
         return _id
 
     def get_payload(self, commit_ids, **kw):
diff --git a/Allura/allura/websetup/__init__.py b/Allura/allura/websetup/__init__.py
index 37b1586..1d5a386 100644
--- a/Allura/allura/websetup/__init__.py
+++ b/Allura/allura/websetup/__init__.py
@@ -19,6 +19,7 @@
 
 """Setup the allura application"""
 
+from __future__ import unicode_literals
 import logging
 
 from allura.config.environment import load_environment
diff --git a/Allura/allura/websetup/bootstrap.py b/Allura/allura/websetup/bootstrap.py
index 14f5660..80bfe16 100644
--- a/Allura/allura/websetup/bootstrap.py
+++ b/Allura/allura/websetup/bootstrap.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 """Setup the allura application"""
+from __future__ import unicode_literals
 import os
 import sys
 import logging
diff --git a/Allura/allura/websetup/schema.py b/Allura/allura/websetup/schema.py
index 86b0f39..3d4df41 100644
--- a/Allura/allura/websetup/schema.py
+++ b/Allura/allura/websetup/schema.py
@@ -19,6 +19,7 @@
 
 """Setup the allura application"""
 
+from __future__ import unicode_literals
 import logging
 
 import activitystream
diff --git a/Allura/docs/conf.py b/Allura/docs/conf.py
index 07c07d0..99ced2c 100644
--- a/Allura/docs/conf.py
+++ b/Allura/docs/conf.py
@@ -37,6 +37,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
 import os
 
 extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx',
@@ -202,8 +203,8 @@ htmlhelp_basename = 'alluradoc'
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title, author, documentclass [howto/manual]).
 latex_documents = [
-    ('index', 'allura.tex', u'allura Documentation',
-     u'Mark Ramm, Wolf, Rick Copeland, Jonathan Beard', 'manual'),
+    ('index', 'allura.tex', 'allura Documentation',
+     'Mark Ramm, Wolf, Rick Copeland, Jonathan Beard', 'manual'),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
diff --git a/Allura/ldap-setup.py b/Allura/ldap-setup.py
index 4f58342..b8b3cb7 100644
--- a/Allura/ldap-setup.py
+++ b/Allura/ldap-setup.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import shutil
 import string
diff --git a/Allura/ldap-userconfig.py b/Allura/ldap-userconfig.py
index bc36c1f..9f37660 100644
--- a/Allura/ldap-userconfig.py
+++ b/Allura/ldap-userconfig.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import sys
 import pwd
diff --git a/Allura/setup.py b/Allura/setup.py
index 47bd1bd..629ff12 100644
--- a/Allura/setup.py
+++ b/Allura/setup.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 b9bc9e7..066bf8c 100644
--- a/AlluraTest/alluratest/controller.py
+++ b/AlluraTest/alluratest/controller.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 """Unit and functional test suite for allura."""
+from __future__ import unicode_literals
 import os
 import urllib
 import json
@@ -68,7 +69,7 @@ def get_config_file(config=None, current_pkg=None):
         conf_file = os.path.join(conf_dir, config)
 
     if not os.path.exists(conf_file.split('#')[0]):
-        raise EnvironmentError(u'Cannot find .ini config file {}'.format(conf_file))
+        raise EnvironmentError('Cannot find .ini config file {}'.format(conf_file))
     else:
         return conf_file
 
diff --git a/AlluraTest/alluratest/pylint_checkers.py b/AlluraTest/alluratest/pylint_checkers.py
index fa2766f..7442aeb 100644
--- a/AlluraTest/alluratest/pylint_checkers.py
+++ b/AlluraTest/alluratest/pylint_checkers.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import astroid
 
 from pylint.checkers import BaseChecker, utils
diff --git a/AlluraTest/alluratest/smtp_debug.py b/AlluraTest/alluratest/smtp_debug.py
index 08a0108..3019e9f 100644
--- a/AlluraTest/alluratest/smtp_debug.py
+++ b/AlluraTest/alluratest/smtp_debug.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from smtpd import DebuggingServer
 
 
diff --git a/AlluraTest/alluratest/test_syntax.py b/AlluraTest/alluratest/test_syntax.py
index 36fa733..7b06d62 100644
--- a/AlluraTest/alluratest/test_syntax.py
+++ b/AlluraTest/alluratest/test_syntax.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os.path
 from subprocess import Popen, PIPE
 import sys
diff --git a/AlluraTest/alluratest/validation.py b/AlluraTest/alluratest/validation.py
index 5076cbe..3972cd4 100644
--- a/AlluraTest/alluratest/validation.py
+++ b/AlluraTest/alluratest/validation.py
@@ -20,6 +20,7 @@
 """
 Functions to syntax-validate output content
 """
+from __future__ import unicode_literals
 from os import path
 import os
 import sys
@@ -144,7 +145,7 @@ def validate_html5(html_or_response):
                 sys.stderr.write('WARNING: ' + resp + '\n')
                 break
 
-    resp = resp.replace(u'“', u'"').replace(u'”', u'"').replace(u'–', u'-')
+    resp = resp.replace('“', '"').replace('”', '"').replace('–', '-')
 
     ignored_errors = [
         'Required attributes missing on element "object"',
diff --git a/AlluraTest/setup.py b/AlluraTest/setup.py
index 056c61d..9286f8b 100644
--- a/AlluraTest/setup.py
+++ b/AlluraTest/setup.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from setuptools import setup, find_packages
 
 setup(name='AlluraTest',
diff --git a/ForgeActivity/forgeactivity/config/resources.py b/ForgeActivity/forgeactivity/config/resources.py
index 5d98bd3..7370f46 100644
--- a/ForgeActivity/forgeactivity/config/resources.py
+++ b/ForgeActivity/forgeactivity/config/resources.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import pkg_resources
 
 
diff --git a/ForgeActivity/forgeactivity/main.py b/ForgeActivity/forgeactivity/main.py
index d66a9b2..32ddf03 100644
--- a/ForgeActivity/forgeactivity/main.py
+++ b/ForgeActivity/forgeactivity/main.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import calendar
 from datetime import timedelta
@@ -158,7 +159,7 @@ class ForgeActivityController(BaseController):
             'link': h.absurl(self.app.url),
             'description': 'Recent activity for %s' % (
                 data['followee'].activity_name),
-            'language': u'en',
+            'language': 'en',
         }
         if request.environ['PATH_INFO'].endswith('.atom'):
             feed = FG.Atom1Feed(**d)
@@ -166,7 +167,7 @@ class ForgeActivityController(BaseController):
             feed = FG.Rss201rev2Feed(**d)
         for t in data['timeline']:
             url = h.absurl(t.obj.activity_url.encode('utf-8'))
-            feed.add_item(title=u'%s %s %s%s' % (
+            feed.add_item(title='%s %s %s%s' % (
                                 t.actor.activity_name,
                 t.verb,
                 t.obj.activity_name,
diff --git a/ForgeActivity/forgeactivity/tests/functional/test_rest.py b/ForgeActivity/forgeactivity/tests/functional/test_rest.py
index 1c99d5f..257b8b7 100644
--- a/ForgeActivity/forgeactivity/tests/functional/test_rest.py
+++ b/ForgeActivity/forgeactivity/tests/functional/test_rest.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 89a3528..2f24766 100644
--- a/ForgeActivity/forgeactivity/tests/functional/test_root.py
+++ b/ForgeActivity/forgeactivity/tests/functional/test_root.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from textwrap import dedent
 
 from mock import patch
diff --git a/ForgeActivity/forgeactivity/widgets/follow.py b/ForgeActivity/forgeactivity/widgets/follow.py
index 97e2f97..907c125 100644
--- a/ForgeActivity/forgeactivity/widgets/follow.py
+++ b/ForgeActivity/forgeactivity/widgets/follow.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from tg import tmpl_context as c
 from formencode import validators as fev
 import ew as ew_core
@@ -50,7 +51,7 @@ class FollowToggle(ew.SimpleForm):
 
     def success_message(self, following):
         context = self.prepare_context({})
-        return u'You are {state} {action}ing {thing}.'.format(
+        return 'You are {state} {action}ing {thing}.'.format(
             state='now' if following else 'no longer',
             action=context['action_label'],
             thing=context['thing'],
diff --git a/ForgeActivity/setup.py b/ForgeActivity/setup.py
index 9795dfb..82db329 100644
--- a/ForgeActivity/setup.py
+++ b/ForgeActivity/setup.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from setuptools import setup, find_packages
 
 setup(name='ForgeActivity',
diff --git a/ForgeBlog/forgeblog/command/base.py b/ForgeBlog/forgeblog/command/base.py
index 8e67cc9..4bcc0fa 100644
--- a/ForgeBlog/forgeblog/command/base.py
+++ b/ForgeBlog/forgeblog/command/base.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from allura.command.base import Command
 
 
diff --git a/ForgeBlog/forgeblog/command/rssfeeds.py b/ForgeBlog/forgeblog/command/rssfeeds.py
index 5ae5fee..49cb12b 100644
--- a/ForgeBlog/forgeblog/command/rssfeeds.py
+++ b/ForgeBlog/forgeblog/command/rssfeeds.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import calendar
 from datetime import datetime
 
@@ -118,7 +119,7 @@ class RssFeedsCommand(base.BlogCommand):
         parsed_content = filter(
             None, e.get('content') or [e.get('summary_detail')])
         if parsed_content:
-            content = u''
+            content = ''
             for ct in parsed_content:
                 if ct.type != 'text/html':
                     content += plain2markdown(ct.value)
@@ -132,7 +133,7 @@ class RssFeedsCommand(base.BlogCommand):
                                              getattr(e, 'subtitle',
                                                      getattr(e, 'title'))))
 
-        content += u' [link](%s)' % e.link
+        content += ' [link](%s)' % e.link
         updated = datetime.utcfromtimestamp(calendar.timegm(e.updated_parsed))
 
         base_slug = BM.BlogPost.make_base_slug(title, updated)
diff --git a/ForgeBlog/forgeblog/main.py b/ForgeBlog/forgeblog/main.py
index d867c1b..30b85c2 100644
--- a/ForgeBlog/forgeblog/main.py
+++ b/ForgeBlog/forgeblog/main.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 #-*- python -*-
+from __future__ import unicode_literals
 import logging
 import urllib2
 import json
@@ -313,7 +314,7 @@ class RootController(BaseController, FeedController):
         self.rate_limit(BM.BlogPost, 'Create/edit', c.app.config.url())
         attachment = kw.pop('attachment', None)
         post = BM.BlogPost.new(**kw)
-        g.spam_checker.check(kw['title'] + u'\n' + kw['text'], artifact=post,
+        g.spam_checker.check(kw['title'] + '\n' + kw['text'], artifact=post,
                              user=c.user, content_type='blog-post')
         if attachment is not None:
             post.add_multiple_attachments(attachment)
@@ -427,7 +428,7 @@ class PostController(BaseController, FeedController):
             flash('Post deleted', 'info')
             redirect(h.really_unicode(c.app.url).encode('utf-8'))
         else:
-            g.spam_checker.check(kw['title'] + u'\n' + kw['text'], artifact=self.post,
+            g.spam_checker.check(kw['title'] + '\n' + kw['text'], artifact=self.post,
                                  user=c.user, content_type='blog-post')
         attachment = kw.pop('attachment', None)
         old_text = self.post.text
diff --git a/ForgeBlog/forgeblog/model/blog.py b/ForgeBlog/forgeblog/model/blog.py
index 5fafd43..e2c536d 100644
--- a/ForgeBlog/forgeblog/model/blog.py
+++ b/ForgeBlog/forgeblog/model/blog.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 39a090c..a90fa68 100644
--- a/ForgeBlog/forgeblog/tests/functional/test_feeds.py
+++ b/ForgeBlog/forgeblog/tests/functional/test_feeds.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 
+from __future__ import unicode_literals
 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 157b387..a2630e7 100644
--- a/ForgeBlog/forgeblog/tests/functional/test_rest.py
+++ b/ForgeBlog/forgeblog/tests/functional/test_rest.py
@@ -16,6 +16,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 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 310f690..9d112c5 100644
--- a/ForgeBlog/forgeblog/tests/functional/test_root.py
+++ b/ForgeBlog/forgeblog/tests/functional/test_root.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import datetime
 import json
 
diff --git a/ForgeBlog/forgeblog/tests/test_app.py b/ForgeBlog/forgeblog/tests/test_app.py
index 24e6bfa..d03460c 100644
--- a/ForgeBlog/forgeblog/tests/test_app.py
+++ b/ForgeBlog/forgeblog/tests/test_app.py
@@ -17,6 +17,7 @@
 
 #-*- python -*-
 
+from __future__ import unicode_literals
 import tempfile
 import json
 import os
diff --git a/ForgeBlog/forgeblog/tests/test_commands.py b/ForgeBlog/forgeblog/tests/test_commands.py
index 87f9c2b..b7531ec 100644
--- a/ForgeBlog/forgeblog/tests/test_commands.py
+++ b/ForgeBlog/forgeblog/tests/test_commands.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from datetime import datetime, timedelta
 from tg import app_globals as g
 from datadiff.tools import assert_equal
@@ -103,12 +104,12 @@ def test_pull_rss_feeds(parsefeed):
 
     base_app = M.AppConfig.query.find().all()[0]
     tmp_app = M.AppConfig(
-        tool_name=u'Blog', discussion_id=base_app.discussion_id,
+        tool_name='Blog', discussion_id=base_app.discussion_id,
         project_id=base_app.project_id,
-        options={u'ordinal': 0, u'show_right_bar': True,
-                 u'project_name': base_app.project.name,
-                 u'mount_point': u'blog',
-                 u'mount_label': u'Blog'})
+        options={'ordinal': 0, 'show_right_bar': True,
+                 'project_name': base_app.project.name,
+                 'mount_point': 'blog',
+                 'mount_label': 'Blog'})
     new_external_feeds = ['http://example.com/news/feed/']
     BM.Globals(app_config_id=tmp_app._id, external_feeds=new_external_feeds)
     ThreadLocalORMSession.flush_all()
diff --git a/ForgeBlog/forgeblog/tests/test_roles.py b/ForgeBlog/forgeblog/tests/test_roles.py
index 3fe6a64..13b82e7 100644
--- a/ForgeBlog/forgeblog/tests/test_roles.py
+++ b/ForgeBlog/forgeblog/tests/test_roles.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 565758a..b42e51b 100644
--- a/ForgeBlog/forgeblog/tests/unit/__init__.py
+++ b/ForgeBlog/forgeblog/tests/unit/__init__.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 b62447e..69e3a6d 100644
--- a/ForgeBlog/forgeblog/tests/unit/test_blog_post.py
+++ b/ForgeBlog/forgeblog/tests/unit/test_blog_post.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from datetime import datetime
 from nose.tools import assert_equal, assert_true
 from tg import tmpl_context as c
diff --git a/ForgeBlog/forgeblog/version.py b/ForgeBlog/forgeblog/version.py
index 1b493f8..192acec 100644
--- a/ForgeBlog/forgeblog/version.py
+++ b/ForgeBlog/forgeblog/version.py
@@ -15,5 +15,6 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeBlog/forgeblog/widgets.py b/ForgeBlog/forgeblog/widgets.py
index 0110b40..1255553 100644
--- a/ForgeBlog/forgeblog/widgets.py
+++ b/ForgeBlog/forgeblog/widgets.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import ew as ew_core
 import ew.jinja2_ew as ew
 
diff --git a/ForgeBlog/setup.py b/ForgeBlog/setup.py
index 7eda917..df75380 100644
--- a/ForgeBlog/setup.py
+++ b/ForgeBlog/setup.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from setuptools import setup, find_packages
 
 from forgeblog.version import __version__
diff --git a/ForgeChat/forgechat/command.py b/ForgeChat/forgechat/command.py
index da2faf8..b82cc05 100644
--- a/ForgeChat/forgechat/command.py
+++ b/ForgeChat/forgechat/command.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import time
 import logging
 import socket
diff --git a/ForgeChat/forgechat/main.py b/ForgeChat/forgechat/main.py
index 981af26..3b65b68 100644
--- a/ForgeChat/forgechat/main.py
+++ b/ForgeChat/forgechat/main.py
@@ -18,6 +18,7 @@
 '''IRC Chatbot Plugin
 '''
 #-*- python -*-
+from __future__ import unicode_literals
 import logging
 from datetime import date, time, datetime, timedelta
 
diff --git a/ForgeChat/forgechat/model/chat.py b/ForgeChat/forgechat/model/chat.py
index 3907101..7513f8e 100644
--- a/ForgeChat/forgechat/model/chat.py
+++ b/ForgeChat/forgechat/model/chat.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 96426c1..1ea95af 100644
--- a/ForgeChat/forgechat/tests/functional/test_root.py
+++ b/ForgeChat/forgechat/tests/functional/test_root.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import json
 from datadiff.tools import assert_equal
 
diff --git a/ForgeChat/forgechat/version.py b/ForgeChat/forgechat/version.py
index 1b493f8..192acec 100644
--- a/ForgeChat/forgechat/version.py
+++ b/ForgeChat/forgechat/version.py
@@ -15,5 +15,6 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeChat/setup.py b/ForgeChat/setup.py
index 242841b..b326d14 100644
--- a/ForgeChat/setup.py
+++ b/ForgeChat/setup.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from setuptools import setup, find_packages
 
 from forgechat.version import __version__
diff --git a/ForgeDiscussion/forgediscussion/controllers/forum.py b/ForgeDiscussion/forgediscussion/controllers/forum.py
index 8fc2d6b..c427d68 100644
--- a/ForgeDiscussion/forgediscussion/controllers/forum.py
+++ b/ForgeDiscussion/forgediscussion/controllers/forum.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import re
 
diff --git a/ForgeDiscussion/forgediscussion/controllers/root.py b/ForgeDiscussion/forgediscussion/controllers/root.py
index b5a459a..0b7d940 100644
--- a/ForgeDiscussion/forgediscussion/controllers/root.py
+++ b/ForgeDiscussion/forgediscussion/controllers/root.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import json
 import logging
 from urllib import unquote
diff --git a/ForgeDiscussion/forgediscussion/forum_main.py b/ForgeDiscussion/forgediscussion/forum_main.py
index 804d349..c7b3d4d 100644
--- a/ForgeDiscussion/forgediscussion/forum_main.py
+++ b/ForgeDiscussion/forgediscussion/forum_main.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 #-*- python -*-
+from __future__ import unicode_literals
 import logging
 import urllib
 import json
diff --git a/ForgeDiscussion/forgediscussion/import_support.py b/ForgeDiscussion/forgediscussion/import_support.py
index a5a3cc0..d31b3a1 100644
--- a/ForgeDiscussion/forgediscussion/import_support.py
+++ b/ForgeDiscussion/forgediscussion/import_support.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 #-*- python -*-
+from __future__ import unicode_literals
 import logging
 from datetime import datetime
 
diff --git a/ForgeDiscussion/forgediscussion/model/forum.py b/ForgeDiscussion/forgediscussion/model/forum.py
index d65e7e2..e4e1b98 100644
--- a/ForgeDiscussion/forgediscussion/model/forum.py
+++ b/ForgeDiscussion/forgediscussion/model/forum.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import re
 import logging
 from itertools import chain
diff --git a/ForgeDiscussion/forgediscussion/site_stats.py b/ForgeDiscussion/forgediscussion/site_stats.py
index cabb5dd..53fef07 100644
--- a/ForgeDiscussion/forgediscussion/site_stats.py
+++ b/ForgeDiscussion/forgediscussion/site_stats.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from datetime import datetime, timedelta
 
 from . import model as DM
diff --git a/ForgeDiscussion/forgediscussion/tasks.py b/ForgeDiscussion/forgediscussion/tasks.py
index cfd5320..265a0db 100644
--- a/ForgeDiscussion/forgediscussion/tasks.py
+++ b/ForgeDiscussion/forgediscussion/tasks.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 262d3a0..ff736b1 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import mock
 import random
 import logging
@@ -352,11 +353,11 @@ class TestForum(TestController):
     def test_unicode_name(self):
         r = self.app.get('/admin/discussion/forums')
         form = r.forms['add-forum']
-        form['add_forum.shortname'] = u'téstforum'.encode('utf-8')
-        form['add_forum.name'] = u'Tést Forum'.encode('utf-8')
+        form['add_forum.shortname'] = 'téstforum'.encode('utf-8')
+        form['add_forum.name'] = 'Tést Forum'.encode('utf-8')
         form.submit()
         r = self.app.get('/admin/discussion/forums')
-        assert u'téstforum'.encode('utf-8') in r
+        assert 'téstforum'.encode('utf-8') in r
 
     def test_markdown_description(self):
         r = self.app.get('/admin/discussion/forums')
@@ -467,7 +468,7 @@ class TestForum(TestController):
         r = self.app.post('/discussion/testforum/moderate/save_moderation_bulk_user', params={
             'username': 'test-admin',
             'spam': '1'})
-        assert_in(u'5 posts marked as spam', self.webflash(r))
+        assert_in('5 posts marked as spam', self.webflash(r))
         assert_equal(5, FM.ForumPost.query.find({'status': 'spam'}).count())
 
     def test_posting(self):
@@ -979,13 +980,13 @@ class TestForum(TestController):
     def test_create_topic_unicode(self):
         r = self.app.get('/admin/discussion/forums')
         form = r.forms['add-forum']
-        form['add_forum.shortname'] = u'téstforum'.encode('utf-8')
-        form['add_forum.name'] = u'Tést Forum'.encode('utf-8')
+        form['add_forum.shortname'] = 'téstforum'.encode('utf-8')
+        form['add_forum.name'] = 'Tést Forum'.encode('utf-8')
         form.submit()
         r = self.app.get('/admin/discussion/forums')
-        assert u'téstforum'.encode('utf-8') in r
-        r = self.app.get(u'/p/test/discussion/create_topic/téstforum/'.encode('utf-8'))
-        assert u'<option value="téstforum" selected>Tést Forum</option>' in r
+        assert 'téstforum'.encode('utf-8') in r
+        r = self.app.get('/p/test/discussion/create_topic/téstforum/'.encode('utf-8'))
+        assert '<option value="téstforum" selected>Tést Forum</option>' in r
 
     def test_create_topic_attachment(self):
         r = self.app.get('/discussion/create_topic/')
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py b/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
index 2d84ada..1b9e54d 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 879b21c..5167448 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 97995d5..7b6a9bc 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from nose.tools import assert_equal, assert_in
 
 from allura.lib import helpers as h
@@ -79,8 +80,8 @@ class TestRootRestController(TestDiscussionApiBase):
         assert_equal(forums[0]['last_post']['subject'], 'Hi guys')
         assert_equal(forums[0]['last_post']['author'], 'test-admin')
         assert_equal(forums[0]['last_post']['text'], 'Hi boys and girls')
-        assert_equal(forums[1]['name'], u'Say Héllo')
-        assert_equal(forums[1]['description'], u'Say héllo here')
+        assert_equal(forums[1]['name'], 'Say Héllo')
+        assert_equal(forums[1]['description'], 'Say héllo here')
         assert_equal(forums[1]['num_topics'], 0)
         assert_equal(
             forums[1]['url'], 'http://localhost/rest/p/test/discussion/h%C3%A9llo/')
@@ -120,7 +121,7 @@ class TestRootRestController(TestDiscussionApiBase):
         self.create_topic('general', 'Hi again', 'It should not be shown')
         t = ForumThread.query.find({'subject': 'Hi again'}).first()
         first_post = t.first_post
-        first_post.status = u'pending'
+        first_post.status = 'pending'
         first_post.commit()
         forum = self.api_get('/rest/p/test/discussion/general/')
         forum = forum.json['forum']
@@ -155,7 +156,7 @@ class TestRootRestController(TestDiscussionApiBase):
         resp = self.app.get('/rest/p/test/discussion/?limit=1&page=1')
         forums = resp.json['forums']
         assert_equal(len(forums), 1)
-        assert_equal(forums[0]['name'], u'Say Héllo')
+        assert_equal(forums[0]['name'], 'Say Héllo')
         assert_equal(resp.json['count'], 2)
         assert_equal(resp.json['page'], 1)
         assert_equal(resp.json['limit'], 1)
@@ -236,7 +237,7 @@ class TestRootRestController(TestDiscussionApiBase):
     def test_private_forums(self):
         r = self.app.get('/p/test/admin/discussion/forums')
         form = r.forms['edit-forums']
-        if form['forum-0.shortname'].value == u'héllo':
+        if form['forum-0.shortname'].value == 'héllo':
             form['forum-0.members_only'] = True
         else:
             form['forum-1.members_only'] = True
diff --git a/ForgeDiscussion/forgediscussion/tests/test_app.py b/ForgeDiscussion/forgediscussion/tests/test_app.py
index e980fc1..d7493d1 100644
--- a/ForgeDiscussion/forgediscussion/tests/test_app.py
+++ b/ForgeDiscussion/forgediscussion/tests/test_app.py
@@ -19,6 +19,7 @@
 
 #-*- python -*-
 
+from __future__ import unicode_literals
 import tempfile
 import json
 import os
@@ -68,22 +69,22 @@ class TestBulkExport(TestDiscussionApiBase):
         discussion = json.loads(f.read())
         forums = sorted(discussion['forums'], key=lambda x: x['name'])
 
-        assert_equal(forums[0]['shortname'], u'general')
+        assert_equal(forums[0]['shortname'], 'general')
         assert_equal(
-            forums[0]['description'], u'Forum about anything you want to talk about.')
-        assert_equal(forums[0]['name'], u'General Discussion')
+            forums[0]['description'], 'Forum about anything you want to talk about.')
+        assert_equal(forums[0]['name'], 'General Discussion')
         forums[0]['threads'] = sorted(forums[0]['threads'],
                                       key=lambda x: x['posts'][0]['subject'])
         assert_equal(
-            forums[0]['threads'][0]['posts'][0]['text'], u'Hi boys and girls')
+            forums[0]['threads'][0]['posts'][0]['text'], 'Hi boys and girls')
         assert_equal(
-            forums[0]['threads'][0]['posts'][0]['subject'], u'Hi guys')
-        assert_equal(forums[0]['threads'][1]['posts'][0]['text'], u'1st post')
+            forums[0]['threads'][0]['posts'][0]['subject'], 'Hi guys')
+        assert_equal(forums[0]['threads'][1]['posts'][0]['text'], '1st post')
         assert_equal(
-            forums[0]['threads'][1]['posts'][0]['subject'], u"Let's talk")
-        assert_equal(forums[1]['shortname'], u'héllo')
-        assert_equal(forums[1]['description'], u'Say héllo here')
-        assert_equal(forums[1]['name'], u'Say Héllo')
+            forums[0]['threads'][1]['posts'][0]['subject'], "Let's talk")
+        assert_equal(forums[1]['shortname'], 'héllo')
+        assert_equal(forums[1]['description'], 'Say héllo here')
+        assert_equal(forums[1]['name'], 'Say Héllo')
 
     def test_export_with_attachments(self):
         project = M.Project.query.get(shortname='test')
diff --git a/ForgeDiscussion/forgediscussion/tests/test_forum_roles.py b/ForgeDiscussion/forgediscussion/tests/test_forum_roles.py
index 4bc0eef..7e688f1 100644
--- a/ForgeDiscussion/forgediscussion/tests/test_forum_roles.py
+++ b/ForgeDiscussion/forgediscussion/tests/test_forum_roles.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 1169caf..76cd473 100644
--- a/ForgeDiscussion/forgediscussion/utils.py
+++ b/ForgeDiscussion/forgediscussion/utils.py
@@ -17,6 +17,7 @@
 
 """ ForgeDiscussion utilities. """
 
+from __future__ import unicode_literals
 from bson import ObjectId
 from tg import flash
 from allura.lib import helpers as h
diff --git a/ForgeDiscussion/forgediscussion/version.py b/ForgeDiscussion/forgediscussion/version.py
index 1b493f8..192acec 100644
--- a/ForgeDiscussion/forgediscussion/version.py
+++ b/ForgeDiscussion/forgediscussion/version.py
@@ -15,5 +15,6 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeDiscussion/forgediscussion/widgets/__init__.py b/ForgeDiscussion/forgediscussion/widgets/__init__.py
index 02bbb9e..cbe2c73 100644
--- a/ForgeDiscussion/forgediscussion/widgets/__init__.py
+++ b/ForgeDiscussion/forgediscussion/widgets/__init__.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       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
diff --git a/ForgeDiscussion/forgediscussion/widgets/admin.py b/ForgeDiscussion/forgediscussion/widgets/admin.py
index 7de847e..af1d079 100644
--- a/ForgeDiscussion/forgediscussion/widgets/admin.py
+++ b/ForgeDiscussion/forgediscussion/widgets/admin.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from formencode import validators as fev
 from formencode import All
 import formencode
@@ -67,7 +68,7 @@ class AddForum(ff.AdminForm):
                          validator=fev.UnicodeString()),
             ew.TextField(name='shortname', label='Short Name',
                          validator=All(
-                             fev.Regex(ur"^[^\s\/\.]*$", not_empty=True, messages={
+                             fev.Regex(r"^[^\s\/\.]*$", not_empty=True, messages={
                                  'invalid': 'Shortname cannot contain space . or /',
                                  'empty': 'You must create a short name for the forum.'}),
                              UniqueForumShortnameValidator())),
diff --git a/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py b/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py
index 046557f..7707e5c 100644
--- a/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py
+++ b/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from tg import tmpl_context as c
 from formencode import validators as fev
 
diff --git a/ForgeDiscussion/setup.py b/ForgeDiscussion/setup.py
index 165ce4b..f6a12f8 100644
--- a/ForgeDiscussion/setup.py
+++ b/ForgeDiscussion/setup.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 889c0f1..bd02001 100755
--- a/ForgeFeedback/forgefeedback/feedback_main.py
+++ b/ForgeFeedback/forgefeedback/feedback_main.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import pymongo
 
diff --git a/ForgeFeedback/forgefeedback/model/feedback.py b/ForgeFeedback/forgefeedback/model/feedback.py
index 9498f70..b3e566f 100755
--- a/ForgeFeedback/forgefeedback/model/feedback.py
+++ b/ForgeFeedback/forgefeedback/model/feedback.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 e99fdb5..45113d8 100755
--- a/ForgeFeedback/forgefeedback/tests/functional/test_root.py
+++ b/ForgeFeedback/forgefeedback/tests/functional/test_root.py
@@ -14,6 +14,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 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 a8ea087..11c1e72 100755
--- a/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py
+++ b/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 193f766..91e95d4 100755
--- a/ForgeFeedback/forgefeedback/tests/unit/__init__.py
+++ b/ForgeFeedback/forgefeedback/tests/unit/__init__.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 03f6944..b7e4154 100755
--- a/ForgeFeedback/forgefeedback/tests/unit/test_feedback.py
+++ b/ForgeFeedback/forgefeedback/tests/unit/test_feedback.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 4b000b1..3acfaa8 100755
--- a/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py
+++ b/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import unittest
 
 from mock import Mock, patch
diff --git a/ForgeFeedback/forgefeedback/version.py b/ForgeFeedback/forgefeedback/version.py
index 3ea72c5..13480d0 100755
--- a/ForgeFeedback/forgefeedback/version.py
+++ b/ForgeFeedback/forgefeedback/version.py
@@ -15,5 +15,6 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeFeedback/setup.py b/ForgeFeedback/setup.py
index cce91c5..0edfbb2 100755
--- a/ForgeFeedback/setup.py
+++ b/ForgeFeedback/setup.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 
+from __future__ import unicode_literals
 from setuptools import setup, find_packages
 
 from forgefeedback.version import __version__
diff --git a/ForgeGit/forgegit/controllers.py b/ForgeGit/forgegit/controllers.py
index d939576..9164b28 100644
--- a/ForgeGit/forgegit/controllers.py
+++ b/ForgeGit/forgegit/controllers.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 27abc42..455efa7 100644
--- a/ForgeGit/forgegit/git_main.py
+++ b/ForgeGit/forgegit/git_main.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 #-*- python -*-
+from __future__ import unicode_literals
 import logging
 
 # Non-stdlib imports
diff --git a/ForgeGit/forgegit/model/git_repo.py b/ForgeGit/forgegit/model/git_repo.py
index c7ed9f0..7cb4bcf 100644
--- a/ForgeGit/forgegit/model/git_repo.py
+++ b/ForgeGit/forgegit/model/git_repo.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import shutil
 import string
@@ -130,7 +131,7 @@ class Repository(M.Repository):
             author = h.really_unicode(c.user.display_name or c.user.username)
             tmp_repo.git.config('user.name', author.encode('utf8'))
             tmp_repo.git.config('user.email', 'allura@localhost')  # a public email alias could be nice here
-            msg = u'Merge {} branch {} into {}\n\n{}'.format(
+            msg = 'Merge {} branch {} into {}\n\n{}'.format(
                 mr.downstream_repo.url(),
                 mr.source_branch,
                 mr.target_branch,
@@ -563,7 +564,7 @@ class GitImplementation(M.RepositoryImplementation):
             try:
                 hex_sha = ref.commit.hexsha
             except (ValueError, AssertionError) as e:
-                log.debug(u"Found invalid sha: {}".format(ref), exc_info=e)
+                log.debug("Found invalid sha: {}".format(ref), exc_info=e)
                 continue
             refs.append(Object(name=ref.name, object_id=hex_sha))
         time_taken = time() - start_time
diff --git a/ForgeGit/forgegit/tests/__init__.py b/ForgeGit/forgegit/tests/__init__.py
index b693039..16153e2 100644
--- a/ForgeGit/forgegit/tests/__init__.py
+++ b/ForgeGit/forgegit/tests/__init__.py
@@ -19,6 +19,7 @@
 
 
 # Make our own Git tool test decorator
+from __future__ import unicode_literals
 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 1a230d4..ec0f980 100644
--- a/ForgeGit/forgegit/tests/functional/test_auth.py
+++ b/ForgeGit/forgegit/tests/functional/test_auth.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 afaaea3..3c18bcd 100644
--- a/ForgeGit/forgegit/tests/functional/test_controllers.py
+++ b/ForgeGit/forgegit/tests/functional/test_controllers.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import json
 import re
 import os
@@ -151,11 +152,11 @@ class TestRootController(_TestCase):
         data = json.loads(resp.body)
         assert_equal(
             data['built_tree']['df30427c488aeab84b2352bdf88a3b19223f9d7a'],
-            {u'url': u'/p/test/src-git/ci/df30427c488aeab84b2352bdf88a3b19223f9d7a/',
-             u'oid': u'df30427c488aeab84b2352bdf88a3b19223f9d7a',
-             u'short_id': u'[df3042]',
-             u'parents': [u'6a45885ae7347f1cac5103b0050cc1be6a1496c8'],
-             u'message': u'Add README', u'row': 2})
+            {'url': '/p/test/src-git/ci/df30427c488aeab84b2352bdf88a3b19223f9d7a/',
+             'oid': 'df30427c488aeab84b2352bdf88a3b19223f9d7a',
+             'short_id': '[df3042]',
+             'parents': ['6a45885ae7347f1cac5103b0050cc1be6a1496c8'],
+             'message': 'Add README', 'row': 2})
 
     def test_commit_browser_basic_view(self):
         resp = self.app.get('/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/basic')
@@ -276,17 +277,17 @@ class TestRootController(_TestCase):
     def test_file_raw(self):
         self._setup_weird_chars_repo()
         ci = self._get_ci(repo='/p/test/weird-chars/')
-        url = ci + 'tree/' + h.urlquote(u'привіт.txt') + '?format=raw'
+        url = ci + 'tree/' + h.urlquote('привіт.txt') + '?format=raw'
         resp = self.app.get(url)
-        assert_in(u'Привіт!\nWhich means Hello!', resp.body.decode('utf-8'))
+        assert_in('Привіт!\nWhich means Hello!', resp.body.decode('utf-8'))
         assert_equal(resp.headers.get('Content-Disposition').decode('utf-8'),
-                     u'attachment;filename="привіт.txt"')
+                     'attachment;filename="привіт.txt"')
 
-        url = ci + 'tree/' + h.urlquote(u'with space.txt') + '?format=raw'
+        url = ci + 'tree/' + h.urlquote('with space.txt') + '?format=raw'
         resp = self.app.get(url)
-        assert_in(u'with space', resp.body.decode('utf-8'))
+        assert_in('with space', resp.body.decode('utf-8'))
         assert_equal(resp.headers.get('Content-Disposition').decode('utf-8'),
-                     u'attachment;filename="with space.txt"')
+                     'attachment;filename="with space.txt"')
 
     def test_invalid_file(self):
         ci = self._get_ci()
diff --git a/ForgeGit/forgegit/tests/model/test_repository.py b/ForgeGit/forgegit/tests/model/test_repository.py
index e277ce0..5799c72 100644
--- a/ForgeGit/forgegit/tests/model/test_repository.py
+++ b/ForgeGit/forgegit/tests/model/test_repository.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import shutil
 import stat
@@ -268,49 +269,49 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
         entries = list(self.repo.log(id_only=False))
         assert_equal(entries, [
             {'authored': {'date': datetime.datetime(2010, 10, 7, 18, 44, 11),
-                          'email': u'rcopeland@geek.net',
-                          'name': u'Rick Copeland'},
+                          'email': 'rcopeland@geek.net',
+                          'name': 'Rick Copeland'},
              'committed': {'date': datetime.datetime(2010, 10, 7, 18, 44, 11),
-                           'email': u'rcopeland@geek.net',
-                           'name': u'Rick Copeland'},
+                           'email': 'rcopeland@geek.net',
+                           'name': 'Rick Copeland'},
              'id': '1e146e67985dcd71c74de79613719bef7bddca4a',
-             'message': u'Change README\n',
+             'message': 'Change README\n',
              'parents': ['df30427c488aeab84b2352bdf88a3b19223f9d7a'],
              'refs': ['HEAD', 'foo', 'master'],
              'size': None,
              'rename_details': {}},
             {'authored': {'date': datetime.datetime(2010, 10, 7, 18, 44, 1),
-                          'email': u'rcopeland@geek.net',
-                          'name': u'Rick Copeland'},
+                          'email': 'rcopeland@geek.net',
+                          'name': 'Rick Copeland'},
              'committed': {'date': datetime.datetime(2010, 10, 7, 18, 44, 1),
-                           'email': u'rcopeland@geek.net',
-                           'name': u'Rick Copeland'},
+                           'email': 'rcopeland@geek.net',
+                           'name': 'Rick Copeland'},
              'id': 'df30427c488aeab84b2352bdf88a3b19223f9d7a',
-             'message': u'Add README\n',
+             'message': 'Add README\n',
              'parents': ['6a45885ae7347f1cac5103b0050cc1be6a1496c8'],
              'refs': [],
              'size': None,
              'rename_details': {}},
             {'authored': {'date': datetime.datetime(2010, 10, 7, 18, 43, 26),
-                          'email': u'rcopeland@geek.net',
-                          'name': u'Rick Copeland'},
+                          'email': 'rcopeland@geek.net',
+                          'name': 'Rick Copeland'},
              'committed': {'date': datetime.datetime(2010, 10, 7, 18, 43, 26),
-                           'email': u'rcopeland@geek.net',
-                           'name': u'Rick Copeland'},
+                           'email': 'rcopeland@geek.net',
+                           'name': 'Rick Copeland'},
              'id': '6a45885ae7347f1cac5103b0050cc1be6a1496c8',
-             'message': u'Remove file\n',
+             'message': 'Remove file\n',
              'parents': ['9a7df788cf800241e3bb5a849c8870f2f8259d98'],
              'refs': [],
              'size': None,
              'rename_details': {}},
             {'authored': {'date': datetime.datetime(2010, 10, 7, 18, 42, 54),
-                          'email': u'rcopeland@geek.net',
-                          'name': u'Rick Copeland'},
+                          'email': 'rcopeland@geek.net',
+                          'name': 'Rick Copeland'},
              'committed': {'date': datetime.datetime(2010, 10, 7, 18, 42, 54),
-                           'email': u'rcopeland@geek.net',
-                           'name': u'Rick Copeland'},
+                           'email': 'rcopeland@geek.net',
+                           'name': 'Rick Copeland'},
              'id': '9a7df788cf800241e3bb5a849c8870f2f8259d98',
-             'message': u'Initial commit\n',
+             'message': 'Initial commit\n',
              'parents': [],
              'refs': [],
              'size': None,
@@ -318,32 +319,32 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
         ])
 
     def test_log_unicode(self):
-        entries = list(self.repo.log(path=u'völundr', id_only=False))
+        entries = list(self.repo.log(path='völundr', id_only=False))
         assert_equal(entries, [])
 
     def test_log_file(self):
         entries = list(self.repo.log(path='README', id_only=False))
         assert_equal(entries, [
             {'authored': {'date': datetime.datetime(2010, 10, 7, 18, 44, 11),
-                          'email': u'rcopeland@geek.net',
-                          'name': u'Rick Copeland'},
+                          'email': 'rcopeland@geek.net',
+                          'name': 'Rick Copeland'},
              'committed': {'date': datetime.datetime(2010, 10, 7, 18, 44, 11),
-                           'email': u'rcopeland@geek.net',
-                           'name': u'Rick Copeland'},
+                           'email': 'rcopeland@geek.net',
+                           'name': 'Rick Copeland'},
              'id': '1e146e67985dcd71c74de79613719bef7bddca4a',
-             'message': u'Change README\n',
+             'message': 'Change README\n',
              'parents': ['df30427c488aeab84b2352bdf88a3b19223f9d7a'],
              'refs': ['HEAD', 'foo', 'master'],
              'size': 28,
              'rename_details': {}},
             {'authored': {'date': datetime.datetime(2010, 10, 7, 18, 44, 1),
-                          'email': u'rcopeland@geek.net',
-                          'name': u'Rick Copeland'},
+                          'email': 'rcopeland@geek.net',
+                          'name': 'Rick Copeland'},
              'committed': {'date': datetime.datetime(2010, 10, 7, 18, 44, 1),
-                           'email': u'rcopeland@geek.net',
-                           'name': u'Rick Copeland'},
+                           'email': 'rcopeland@geek.net',
+                           'name': 'Rick Copeland'},
              'id': 'df30427c488aeab84b2352bdf88a3b19223f9d7a',
-             'message': u'Add README\n',
+             'message': 'Add README\n',
              'parents': ['6a45885ae7347f1cac5103b0050cc1be6a1496c8'],
              'refs': [],
              'size': 15,
@@ -393,7 +394,7 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
             self.repo, ['1e146e67985dcd71c74de79613719bef7bddca4a', ])
         ThreadLocalORMSession.flush_all()
 
-        n = M.Notification.query.find({'subject': u'[test:src-git] New commit [1e146e] by Rick Copeland'}).first()
+        n = M.Notification.query.find({'subject': '[test:src-git] New commit [1e146e] by Rick Copeland'}).first()
         assert n
         assert_in('Change README', n.text)
 
@@ -403,7 +404,7 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
                                        ])
         ThreadLocalORMSession.flush_all()
         n = M.Notification.query.find(
-            dict(subject=u'[test:src-git] 2 new commits to Git')).first()
+            dict(subject='[test:src-git] 2 new commits to Git')).first()
         assert n
         assert n.text.startswith('\n## Branch: master'), n.text
         assert n.text.find('Add README') < n.text.find('Change README'), n.text
@@ -415,7 +416,7 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
                                        ])
         ThreadLocalORMSession.flush_all()
         n = M.Notification.query.find(
-            dict(subject=u'[test:src-git] 3 new commits to Git')).first()
+            dict(subject='[test:src-git] 3 new commits to Git')).first()
         assert n
         assert n.text.startswith('\n## Branch: master'), n.text
         assert n.text.find('Add README') < n.text.find('Change README'), n.text
@@ -430,7 +431,7 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
                                        ])
         ThreadLocalORMSession.flush_all()
         n = M.Notification.query.find(
-            dict(subject=u'[test:src-git] 4 new commits to Git')).first()
+            dict(subject='[test:src-git] 4 new commits to Git')).first()
         assert n
         assert n.text.startswith('\n## Branch: master'), n.text
         assert n.text.endswith('And 1 more commits.\n'), n.text
@@ -513,17 +514,17 @@ By Dave Brondsema''', text_body)
         c.lcid_cache = {}  # else it'll be a mock
         lcd_map = self.repo.commit('HEAD').tree.ls()
         self.assertEqual(lcd_map, [{
-            'href': u'README',
+            'href': 'README',
             'kind': 'BLOB',
             'last_commit': {
-                    'author': u'Rick Copeland',
-                'author_email': u'rcopeland@geek.net',
+                    'author': 'Rick Copeland',
+                'author_email': 'rcopeland@geek.net',
                 'author_url': None,
                 'date': datetime.datetime(2010, 10, 7, 18, 44, 11),
-                'href': u'/p/test/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/',
-                'shortlink': u'[1e146e]',
-                'summary': u'Change README'},
-            'name': u'README'}])
+                'href': '/p/test/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/',
+                'shortlink': '[1e146e]',
+                'summary': 'Change README'},
+            'name': 'README'}])
 
     def test_ls_with_prev(self):
         c.lcid_cache = {}  # else it'll be a mock
@@ -654,46 +655,46 @@ By Dave Brondsema''', text_body)
         payload = sender.get_payload(commit_ids=cids, ref='refs/heads/zz')
         expected_payload = {
             'size': 2,
-            'ref': u'refs/heads/zz',
-            'after': u'5c47243c8e424136fd5cdd18cd94d34c66d1955c',
-            'before': u'df30427c488aeab84b2352bdf88a3b19223f9d7a',
+            'ref': 'refs/heads/zz',
+            'after': '5c47243c8e424136fd5cdd18cd94d34c66d1955c',
+            'before': 'df30427c488aeab84b2352bdf88a3b19223f9d7a',
             'commits': [{
-                'id': u'5c47243c8e424136fd5cdd18cd94d34c66d1955c',
-                'url': u'http://localhost/p/test/src-git/ci/5c47243c8e424136fd5cdd18cd94d34c66d1955c/',
+                'id': '5c47243c8e424136fd5cdd18cd94d34c66d1955c',
+                'url': 'http://localhost/p/test/src-git/ci/5c47243c8e424136fd5cdd18cd94d34c66d1955c/',
                 'timestamp': datetime.datetime(2013, 3, 28, 18, 54, 16),
-                'message': u'Not repo root',
-                'author': {'name': u'Cory Johns',
-                           'email': u'cjohns@slashdotmedia.com',
+                'message': 'Not repo root',
+                'author': {'name': 'Cory Johns',
+                           'email': 'cjohns@slashdotmedia.com',
                            'username': 'cory'},
-                'committer': {'name': u'Cory Johns',
-                              'email': u'cjohns@slashdotmedia.com',
+                'committer': {'name': 'Cory Johns',
+                              'email': 'cjohns@slashdotmedia.com',
                               'username': 'cory'},
-                'added': [u'bad'],
+                'added': ['bad'],
                 'removed': [],
                 'modified': [],
                 'copied': [],
                 'renamed': [],
             }, {
-                'id': u'1e146e67985dcd71c74de79613719bef7bddca4a',
-                'url': u'http://localhost/p/test/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/',
+                'id': '1e146e67985dcd71c74de79613719bef7bddca4a',
+                'url': 'http://localhost/p/test/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/',
                 'timestamp': datetime.datetime(2010, 10, 7, 18, 44, 11),
-                'message': u'Change README',
-                'author': {'name': u'Rick Copeland',
-                           'email': u'rcopeland@geek.net',
+                'message': 'Change README',
+                'author': {'name': 'Rick Copeland',
+                           'email': 'rcopeland@geek.net',
                            'username': 'rick'},
-                'committer': {'name': u'Rick Copeland',
-                              'email': u'rcopeland@geek.net',
+                'committer': {'name': 'Rick Copeland',
+                              'email': 'rcopeland@geek.net',
                               'username': 'rick'},
                 'added': [],
                 'removed': [],
-                'modified': [u'README'],
+                'modified': ['README'],
                 'copied': [],
                 'renamed': [],
             }],
             'repository': {
-                'name': u'Git',
-                'full_name': u'/p/test/src-git/',
-                'url': u'http://localhost/p/test/src-git/',
+                'name': 'Git',
+                'full_name': '/p/test/src-git/',
+                'url': 'http://localhost/p/test/src-git/',
             },
         }
         assert_equals(payload, expected_payload)
@@ -746,8 +747,8 @@ By Dave Brondsema''', text_body)
             tmp_repo.git.config.call_args_list,
             [mock.call('user.name', 'Test Admin'),
              mock.call('user.email', 'allura@localhost')])
-        msg = u'Merge downstream-repo-url branch source-branch into target-branch'
-        msg += u'\n\nhttp://localhost/merge-request/1/'
+        msg = 'Merge downstream-repo-url branch source-branch into target-branch'
+        msg += '\n\nhttp://localhost/merge-request/1/'
         tmp_repo.git.merge.assert_called_once_with('cid', '-m', msg)
         tmp_repo.git.push.assert_called_once_with('origin', 'target-branch')
         shutil.rmtree.assert_called_once_with(
@@ -787,7 +788,7 @@ By Dave Brondsema''', text_body)
             'removed': [],
             'changed': [],
             'renamed': [],
-            'added': [u'with space.txt', u'привіт.txt'],
+            'added': ['with space.txt', 'привіт.txt'],
             'copied': [],
             'total': 2,
         }
@@ -799,7 +800,7 @@ By Dave Brondsema''', text_body)
             'removed': [],
             'copied': [],
             'renamed': [],
-            'changed': [u'привіт.txt'],
+            'changed': ['привіт.txt'],
             'total': 1,
         }
         assert_equals(diffs, expected)
@@ -807,7 +808,7 @@ By Dave Brondsema''', text_body)
         # initial commit is special, but must work too
         diffs = repo.paged_diffs('afaa6d93eb5661fb04f8e10e9ba1039b7441a6c7')
         expected = {
-            'added': [u'README.md'],
+            'added': ['README.md'],
             'removed': [],
             'changed': [],
             'copied': [],
@@ -819,7 +820,7 @@ By Dave Brondsema''', text_body)
         # pagination
         diffs = repo.paged_diffs('407950e8fba4dbc108ffbce0128ed1085c52cfd7', start=0, end=1)
         expected = {
-            'added': [u'with space.txt'],
+            'added': ['with space.txt'],
             'removed': [],
             'copied': [],
             'renamed': [],
@@ -829,7 +830,7 @@ By Dave Brondsema''', text_body)
         assert_equals(diffs, expected)
         diffs = repo.paged_diffs('407950e8fba4dbc108ffbce0128ed1085c52cfd7', start=1, end=2)
         expected = {
-            'added': [u'привіт.txt'],
+            'added': ['привіт.txt'],
             'removed': [],
             'copied': [],
             'renamed': [],
@@ -839,18 +840,18 @@ By Dave Brondsema''', text_body)
         assert_equals(diffs, expected)
         diffs = repo.paged_diffs('346c52c1dddc729e2c2711f809336401f0ff925e')  # Test copy
         expected = {
-            'added': [u'README.copy'],
+            'added': ['README.copy'],
             'removed': [],
             'copied': [],
             'renamed': [],
-            'changed': [u'README'],
+            'changed': ['README'],
             'total': 2,
         }
         assert_equals(diffs, expected)
         diffs = repo.paged_diffs('3cb2bbcd7997f89060a14fe8b1a363f01883087f')  # Test rename
         expected = {
-            'added': [u'README'],
-            'removed': [u'README-copy.md'],
+            'added': ['README'],
+            'removed': ['README-copy.md'],
             'copied': [],
             'renamed': [],
             'changed': [],
@@ -863,7 +864,7 @@ By Dave Brondsema''', text_body)
             'removed': [],
             'copied': [],
             'renamed': [],
-            'changed': [u'README.copy'],
+            'changed': ['README.copy'],
             'total': 1,
         }
         assert_equals(diffs, expected)
@@ -889,9 +890,9 @@ By Dave Brondsema''', text_body)
         expected = {
             'added': [],
             'removed': [],
-            'copied': [{'new': u'README.copy', 'old': u'README', 'ratio': 1.0}],
+            'copied': [{'new': 'README.copy', 'old': 'README', 'ratio': 1.0}],
             'renamed': [],
-            'changed': [u'README'],
+            'changed': ['README'],
             'total': 2,
         }
         assert_equals(diffs, expected)
@@ -900,7 +901,7 @@ By Dave Brondsema''', text_body)
             'added': [],
             'removed': [],
             'copied': [],
-            'renamed': [{'new': u'README', 'old': u'README-copy.md', 'ratio': 1.0}],
+            'renamed': [{'new': 'README', 'old': 'README-copy.md', 'ratio': 1.0}],
             'changed': [],
             'total': 1,
         }
@@ -915,14 +916,14 @@ By Dave Brondsema''', text_body)
         expected = [
             {'authored': {
                 'date': datetime.datetime(2013, 3, 28, 18, 54, 16),
-                'email': u'cjohns@slashdotmedia.com',
-                'name': u'Cory Johns'},
+                'email': 'cjohns@slashdotmedia.com',
+                'name': 'Cory Johns'},
              'committed': {
                  'date': datetime.datetime(2013, 3, 28, 18, 54, 16),
-                 'email': u'cjohns@slashdotmedia.com',
-                 'name': u'Cory Johns'},
+                 'email': 'cjohns@slashdotmedia.com',
+                 'name': 'Cory Johns'},
              'id': '5c47243c8e424136fd5cdd18cd94d34c66d1955c',
-             'message': u'Not repo root\n',
+             'message': 'Not repo root\n',
              'parents': ['1e146e67985dcd71c74de79613719bef7bddca4a'],
              'refs': ['zz'],
              'rename_details': {},
diff --git a/ForgeGit/forgegit/tests/test_git_app.py b/ForgeGit/forgegit/tests/test_git_app.py
index c03e242..b43aac5 100644
--- a/ForgeGit/forgegit/tests/test_git_app.py
+++ b/ForgeGit/forgegit/tests/test_git_app.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 4563457..37248f0 100644
--- a/ForgeGit/forgegit/tests/test_tasks.py
+++ b/ForgeGit/forgegit/tests/test_tasks.py
@@ -14,6 +14,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 import unittest
 import mock
 from testfixtures import LogCapture
diff --git a/ForgeGit/forgegit/version.py b/ForgeGit/forgegit/version.py
index 1b493f8..192acec 100644
--- a/ForgeGit/forgegit/version.py
+++ b/ForgeGit/forgegit/version.py
@@ -15,5 +15,6 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeGit/setup.py b/ForgeGit/setup.py
index e91068b..8ceb54b 100644
--- a/ForgeGit/setup.py
+++ b/ForgeGit/setup.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from setuptools import setup, find_packages
 
 from forgegit.version import __version__
diff --git a/ForgeImporters/docs/conf.py b/ForgeImporters/docs/conf.py
index ff9275c..2fb71f0 100644
--- a/ForgeImporters/docs/conf.py
+++ b/ForgeImporters/docs/conf.py
@@ -37,6 +37,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
 extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx',
               'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.ifconfig']
 
@@ -187,8 +188,8 @@ htmlhelp_basename = 'alluradoc'
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title, author, documentclass [howto/manual]).
 latex_documents = [
-    ('index', 'allura.tex', u'allura Documentation',
-     u'Cory Johns, Tim Van Steenburgh, Dave Brondsema', 'manual'),
+    ('index', 'allura.tex', 'allura Documentation',
+     'Cory Johns, Tim Van Steenburgh, Dave Brondsema', 'manual'),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
diff --git a/ForgeImporters/forgeimporters/base.py b/ForgeImporters/forgeimporters/base.py
index d7ea454..91d025e 100644
--- a/ForgeImporters/forgeimporters/base.py
+++ b/ForgeImporters/forgeimporters/base.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import errno
 import logging
diff --git a/ForgeImporters/forgeimporters/forge/tracker.py b/ForgeImporters/forgeimporters/forge/tracker.py
index 32ec0eb..e7024c1 100644
--- a/ForgeImporters/forgeimporters/forge/tracker.py
+++ b/ForgeImporters/forgeimporters/forge/tracker.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import json
 
diff --git a/ForgeImporters/forgeimporters/github/__init__.py b/ForgeImporters/forgeimporters/github/__init__.py
index e294ee1..ac538c5 100644
--- a/ForgeImporters/forgeimporters/github/__init__.py
+++ b/ForgeImporters/forgeimporters/github/__init__.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import re
 import logging
 import json
diff --git a/ForgeImporters/forgeimporters/github/code.py b/ForgeImporters/forgeimporters/github/code.py
index 9d6e5f5..ac53bce 100644
--- a/ForgeImporters/forgeimporters/github/code.py
+++ b/ForgeImporters/forgeimporters/github/code.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 c4d8c61..7586971 100644
--- a/ForgeImporters/forgeimporters/github/project.py
+++ b/ForgeImporters/forgeimporters/github/project.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 
 from tg import expose, validate
diff --git a/ForgeImporters/forgeimporters/github/tasks.py b/ForgeImporters/forgeimporters/github/tasks.py
index db12c4d..a1cd9bb 100644
--- a/ForgeImporters/forgeimporters/github/tasks.py
+++ b/ForgeImporters/forgeimporters/github/tasks.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 bc293ce..0f7bc09 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_code.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_code.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from unittest import TestCase
 from mock import Mock, patch
 from ming.odm import ThreadLocalORMSession
@@ -96,12 +97,12 @@ class TestGitHubImportController(TestController, TestCase):
             r.location, 'http://localhost/p/{}/admin/'.format(
                 test_project_with_repo))
         self.assertEqual(
-            u'mymount', import_tool.post.call_args[1]['mount_point'])
+            'mymount', import_tool.post.call_args[1]['mount_point'])
         self.assertEqual(
-            u'mylabel', import_tool.post.call_args[1]['mount_label'])
+            'mylabel', import_tool.post.call_args[1]['mount_label'])
         self.assertEqual(
-            u'poop', import_tool.post.call_args[1]['project_name'])
-        self.assertEqual(u'spooky', import_tool.post.call_args[1]['user_name'])
+            'poop', import_tool.post.call_args[1]['project_name'])
+        self.assertEqual('spooky', import_tool.post.call_args[1]['user_name'])
         self.assertEqual(requests.head.call_count, 1)
 
     @with_git
diff --git a/ForgeImporters/forgeimporters/github/tests/test_oauth.py b/ForgeImporters/forgeimporters/github/tests/test_oauth.py
index a903623..ddbe89b 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_oauth.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_oauth.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 b2cda37..a25ccd5 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_tracker.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_tracker.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from unittest import TestCase
 from mock import patch
 from ming.odm import ThreadLocalORMSession
@@ -58,12 +59,12 @@ class TestGitHubTrackerImportController(TestController, TestCase):
         self.assertEqual(r.location, 'http://localhost/p/%s/admin/' %
                          test_project_with_tracker)
         self.assertEqual(
-            u'Issues', import_tool.post.call_args[1]['mount_label'])
+            'Issues', import_tool.post.call_args[1]['mount_label'])
         self.assertEqual(
-            u'issues', import_tool.post.call_args[1]['mount_point'])
+            'issues', import_tool.post.call_args[1]['mount_point'])
         self.assertEqual(
-            u'mulder', import_tool.post.call_args[1]['project_name'])
-        self.assertEqual(u'spooky', import_tool.post.call_args[1]['user_name'])
+            'mulder', import_tool.post.call_args[1]['project_name'])
+        self.assertEqual('spooky', import_tool.post.call_args[1]['user_name'])
         self.assertEqual(requests.head.call_count, 1)
 
     @with_tracker
diff --git a/ForgeImporters/forgeimporters/github/tests/test_utils.py b/ForgeImporters/forgeimporters/github/tests/test_utils.py
index 6ce7821..0f482a2 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_utils.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_utils.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from nose.tools import assert_equal
 
 from forgeimporters.github.utils import GitHubMarkdownConverter
@@ -86,12 +87,12 @@ class TestGitHubMarkdownConverter(object):
         assert_equal(self.conv.convert(text), '<s>mistake</s>')
 
     def test_inline_code_block(self):
-        text = u'This `~~some text~~` converts to this ~~strike out~~.'
-        result = u'This `~~some text~~` converts to this <s>strike out</s>.'
+        text = 'This `~~some text~~` converts to this ~~strike out~~.'
+        result = 'This `~~some text~~` converts to this <s>strike out</s>.'
         assert_equal(self.conv.convert(text).strip(), result)
 
     def test_convert_code_blocks(self):
-        text = u'''```python
+        text = '''```python
 print "Hello!"
 ```
 
@@ -102,7 +103,7 @@ for (var i = 0; i < a.length; i++) {
     console.log(i);
 }
 ```'''
-        result = u''':::python
+        result = ''':::python
     print "Hello!"
 
 Two code blocks here!
@@ -114,14 +115,14 @@ Two code blocks here!
         assert_equal(self.conv.convert(text).strip(), result)
 
     def test_code_blocks_without_newline_before(self):
-        text = u'''
+        text = '''
 There are some code snippet:
 ```
 print 'Hello'
 ```
 Pretty cool, ha?'''
 
-        result = u'''
+        result = '''
 There are some code snippet:
 
     print 'Hello'
@@ -130,14 +131,14 @@ Pretty cool, ha?'''
         text = text.replace('```', '~~~')
         assert_equal(self.conv.convert(text).strip(), result.strip())
 
-        text = u'''
+        text = '''
 There are some code snippet:
 ```python
 print 'Hello'
 ```
 Pretty cool, ha?'''
 
-        result = u'''
+        result = '''
 There are some code snippet:
 
     :::python
diff --git a/ForgeImporters/forgeimporters/github/tests/test_wiki.py b/ForgeImporters/forgeimporters/github/tests/test_wiki.py
index f99ecc4..8f21f55 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_wiki.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_wiki.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from unittest import TestCase
 from nose.tools import assert_equal
 from mock import Mock, patch, call
@@ -137,8 +138,8 @@ class TestGitHubWikiImporter(TestCase):
         assert_equal(upsert.call_args_list, [call('Home2'), call('Home3')])
 
         assert_equal(render.call_args_list, [
-            call('Home2.creole', u'**test message**'),
-            call('Home3.rest', u'test message')])
+            call('Home2.creole', '**test message**'),
+            call('Home3.rest', 'test message')])
 
     @patch('forgeimporters.github.wiki.git.Repo')
     @patch('forgeimporters.github.wiki.mkdtemp')
@@ -182,7 +183,7 @@ class TestGitHubWikiImporter(TestCase):
         importer._with_history(self.commit2)
         assert_equal(upsert.call_args_list, [call('Home')])
         assert_equal(render.call_args_list,
-                     [call('Home.rst', u'# test message')])
+                     [call('Home.rst', '# test message')])
 
     @skipif(module_not_available('html2text'))
     @patch('forgeimporters.github.wiki.WM.Page.upsert')
@@ -190,7 +191,7 @@ class TestGitHubWikiImporter(TestCase):
     def test_with_history_mediawiki(self, md2mkm, upsert):
         self.commit2.stats.files = {"Home.mediawiki": self.blob1}
         self.commit2.tree = {"Home.mediawiki": self.blob1}
-        md2mkm.return_value = u'# test message'
+        md2mkm.return_value = '# test message'
         importer = GitHubWikiImporter()
         importer._set_available_pages = Mock()
         importer.github_wiki_url = 'https://github.com/a/b/wiki'
@@ -198,28 +199,28 @@ class TestGitHubWikiImporter(TestCase):
         importer.app.config.options = {}
         importer.app.url = '/p/test/wiki/'
         importer.rewrite_links = Mock(return_value='')
-        importer.convert_gollum_tags = Mock(return_value=u'# test message')
+        importer.convert_gollum_tags = Mock(return_value='# test message')
         importer._with_history(self.commit2)
         assert_equal(upsert.call_args_list, [call('Home')])
-        assert_equal(md2mkm.call_args_list, [call(u'# test message')])
+        assert_equal(md2mkm.call_args_list, [call('# test message')])
 
     def test_set_available_pages(self):
         importer = GitHubWikiImporter()
         commit = Mock()
         blobs = [Mock() for i in range(3)]
-        blobs[0].name = u'Home-42.md'
-        blobs[1].name = u'image.png'
-        blobs[2].name = u'code & fun.textile'
+        blobs[0].name = 'Home-42.md'
+        blobs[1].name = 'image.png'
+        blobs[2].name = 'code & fun.textile'
         commit.tree.traverse.return_value = blobs
         importer._set_available_pages(commit)
-        assert_equal(importer.available_pages, [u'Home 42', u'code & fun'])
+        assert_equal(importer.available_pages, ['Home 42', 'code & fun'])
 
     def test_gollum_page_links_case_insensitive(self):
         i = GitHubWikiImporter()
-        i.available_pages = [u'Home 42', u'code & fun']
-        assert_equal(i.convert_gollum_tags(u'[[Code & Fun]]'), u'[code & fun]')
-        assert_equal(i.convert_gollum_tags(u'[[home-42]]'), u'[Home 42]')
-        assert_equal(i.convert_gollum_tags(u'[[Unknown]]'), u'[Unknown]')
+        i.available_pages = ['Home 42', 'code & fun']
+        assert_equal(i.convert_gollum_tags('[[Code & Fun]]'), '[code & fun]')
+        assert_equal(i.convert_gollum_tags('[[home-42]]'), '[Home 42]')
+        assert_equal(i.convert_gollum_tags('[[Unknown]]'), '[Unknown]')
 
     def test_convert_page_name(self):
         f = GitHubWikiImporter()._convert_page_name
@@ -229,57 +230,57 @@ class TestGitHubWikiImporter(TestCase):
 
     def test_convert_gollum_page_links(self):
         f = GitHubWikiImporter().convert_gollum_tags
-        assert_equal(f(u'[[Page]]'), u'[Page]')
-        assert_equal(f(u'[[Page Title|Page]]'), u'[Page Title](Page)')
-        assert_equal(f(u'[[Pagê Nâme]]'), u'[Pagê Nâme]')
+        assert_equal(f('[[Page]]'), '[Page]')
+        assert_equal(f('[[Page Title|Page]]'), '[Page Title](Page)')
+        assert_equal(f('[[Pagê Nâme]]'), '[Pagê Nâme]')
         # Github always converts spaces and slashes in links to hyphens,
         # to lookup page in the filesystem. During import we're converting
         # all hyphens in page name to spaces, but still supporting both link
         # formats.
-        assert_equal(f(u'[[Page With Spaces]]'), u'[Page With Spaces]')
-        assert_equal(f(u'[[Page-With-Spaces]]'), u'[Page With Spaces]')
-        assert_equal(f(u'[[Page / 1]]'), u'[Page   1]')
-        assert_equal(f(u'[[Title|Page With Spaces]]'),
-                     u'[Title](Page With Spaces)')
-        assert_equal(f(u'[[Title|Page-With-Spaces]]'),
-                     u'[Title](Page With Spaces)')
-        assert_equal(f(u'[[go here|Page / 1]]'), u'[go here](Page   1)')
+        assert_equal(f('[[Page With Spaces]]'), '[Page With Spaces]')
+        assert_equal(f('[[Page-With-Spaces]]'), '[Page With Spaces]')
+        assert_equal(f('[[Page / 1]]'), '[Page   1]')
+        assert_equal(f('[[Title|Page With Spaces]]'),
+                     '[Title](Page With Spaces)')
+        assert_equal(f('[[Title|Page-With-Spaces]]'),
+                     '[Title](Page With Spaces)')
+        assert_equal(f('[[go here|Page / 1]]'), '[go here](Page   1)')
 
     def test_convert_gollum_page_links_escaped(self):
         f = GitHubWikiImporter().convert_gollum_tags
-        assert_equal(f(u"'[[Page]]"), u'[[Page]]')
-        assert_equal(f(u"'[[Page Title|Page]]"), u'[[Page Title|Page]]')
-        assert_equal(f(u"'[[Page With Spaces]]"), u'[[Page With Spaces]]')
-        assert_equal(f(u"'[[Page-With-Spaces]]"), u'[[Page-With-Spaces]]')
-        assert_equal(f(u"'[[Page / 1]]"), u'[[Page / 1]]')
-        assert_equal(f(u"'[[Title|Page With Spaces]]"),
-                     u'[[Title|Page With Spaces]]')
-        assert_equal(f(u"'[[Title|Page-With-Spaces]]"),
-                     u'[[Title|Page-With-Spaces]]')
-        assert_equal(f(u"'[[go here|Page / 1]]"), u'[[go here|Page / 1]]')
+        assert_equal(f("'[[Page]]"), '[[Page]]')
+        assert_equal(f("'[[Page Title|Page]]"), '[[Page Title|Page]]')
+        assert_equal(f("'[[Page With Spaces]]"), '[[Page With Spaces]]')
+        assert_equal(f("'[[Page-With-Spaces]]"), '[[Page-With-Spaces]]')
+        assert_equal(f("'[[Page / 1]]"), '[[Page / 1]]')
+        assert_equal(f("'[[Title|Page With Spaces]]"),
+                     '[[Title|Page With Spaces]]')
+        assert_equal(f("'[[Title|Page-With-Spaces]]"),
+                     '[[Title|Page-With-Spaces]]')
+        assert_equal(f("'[[go here|Page / 1]]"), '[[go here|Page / 1]]')
 
     def test_convert_gollum_external_links(self):
         f = GitHubWikiImporter().convert_gollum_tags
-        assert_equal(f(u'[[http://domain.net]]'), u'<http://domain.net>')
-        assert_equal(f(u'[[https://domain.net]]'), u'<https://domain.net>')
-        assert_equal(f(u'[[Site|http://domain.net]]'),
-                     u'[Site](http://domain.net)')
+        assert_equal(f('[[http://domain.net]]'), '<http://domain.net>')
+        assert_equal(f('[[https://domain.net]]'), '<https://domain.net>')
+        assert_equal(f('[[Site|http://domain.net]]'),
+                     '[Site](http://domain.net)')
 
     def test_convert_gollum_external_links_escaped(self):
         f = GitHubWikiImporter().convert_gollum_tags
-        assert_equal(f(u"'[[http://domain.net]]"), u'[[http://domain.net]]')
-        assert_equal(f(u"'[[https://domain.net]]"), u'[[https://domain.net]]')
-        assert_equal(f(u"'[[Site|http://domain.net]]"),
-                     u'[[Site|http://domain.net]]')
+        assert_equal(f("'[[http://domain.net]]"), '[[http://domain.net]]')
+        assert_equal(f("'[[https://domain.net]]"), '[[https://domain.net]]')
+        assert_equal(f("'[[Site|http://domain.net]]"),
+                     '[[Site|http://domain.net]]')
 
     def test_convert_gollum_toc(self):
         f = GitHubWikiImporter().convert_gollum_tags
-        assert_equal(f(u'[[_TOC_]]'), u'[TOC]')
-        assert_equal(f(u"'[[_TOC_]]"), u'[[_TOC_]]')
+        assert_equal(f('[[_TOC_]]'), '[TOC]')
+        assert_equal(f("'[[_TOC_]]"), '[[_TOC_]]')
 
     def test_convert_gollum_tags(self):
         f = GitHubWikiImporter().convert_gollum_tags
-        source = u'''Look at [[this page|Some Page]]
+        source = '''Look at [[this page|Some Page]]
 
 More info at: [[MoreInfo]] [[Even More Info]]
 
@@ -287,7 +288,7 @@ Our website is [[http://domain.net]].
 
 '[[Escaped Tag]]'''
 
-        result = u'''Look at [this page](Some Page)
+        result = '''Look at [this page](Some Page)
 
 More info at: [MoreInfo] [Even More Info]
 
@@ -306,7 +307,7 @@ Our website is <http://domain.net>.
         importer.github_markdown_converter = GitHubMarkdownConverter(
             'user', 'proj')
         f = importer.convert_markup
-        source = u'''Look at [[this page|Some Page]]
+        source = '''Look at [[this page|Some Page]]
 
 More info at: [[MoreInfo]] [[Even More Info]]
 
@@ -323,7 +324,7 @@ ticket #1
 #1 header
 
 sha aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'''
-        result = u'''Look at [this page](Some Page)
+        result = '''Look at [this page](Some Page)
 
 More info at: [MoreInfo] [Even More Info]
 
@@ -341,7 +342,7 @@ ticket [#1]
 sha [aaaaaa]'''
         assert_equal(f(source, 'test.md').strip(), result)
 
-        assert_equal(f(u'h1. Hello', 't.textile').strip(), u'# Hello')
+        assert_equal(f('h1. Hello', 't.textile').strip(), '# Hello')
 
     @without_module('html2text')
     def test_convert_markup_without_html2text(self):
@@ -350,7 +351,7 @@ sha [aaaaaa]'''
         importer.app = Mock()
         importer.app.url = '/p/test/wiki/'
         f = importer.convert_markup
-        source = u'''Look at [[this page|Some Page]]
+        source = '''Look at [[this page|Some Page]]
 
 More info at: [[MoreInfo]] [[Even More Info]]
 
@@ -362,7 +363,7 @@ Our website is [[http://domain.net]].
 
 [External link](https://github.com/a/b/issues/1)'''
 
-        result = u'''<p>Look at [[this page|Some Page]]</p>
+        result = '''<p>Look at [[this page|Some Page]]</p>
 <p>More info at: [[MoreInfo]] [[Even More Info]]</p>
 <p>Our website is [[http://domain.net]].</p>
 <p>\u2018[[Escaped Tag]]</p>
@@ -376,29 +377,29 @@ Our website is [[http://domain.net]].
         prefix = 'https://github/a/b/wiki'
         new = '/p/test/wiki/'
         assert_equal(
-            f(u'<a href="https://github/a/b/wiki/Test Page">Test Page</a>',
+            f('<a href="https://github/a/b/wiki/Test Page">Test Page</a>',
               prefix, new),
-            u'<a href="/p/test/wiki/Test Page">Test Page</a>')
+            '<a href="/p/test/wiki/Test Page">Test Page</a>')
         assert_equal(
-            f(u'<a href="https://github/a/b/wiki/Test-Page">Test-Page</a>',
+            f('<a href="https://github/a/b/wiki/Test-Page">Test-Page</a>',
               prefix, new),
-            u'<a href="/p/test/wiki/Test Page">Test Page</a>')
+            '<a href="/p/test/wiki/Test Page">Test Page</a>')
         assert_equal(
-            f(u'<a href="https://github/a/b/issues/1" class="1"></a>',
+            f('<a href="https://github/a/b/issues/1" class="1"></a>',
               prefix, new),
-            u'<a class="1" href="https://github/a/b/issues/1"></a>')
+            '<a class="1" href="https://github/a/b/issues/1"></a>')
         assert_equal(
-            f(u'<a href="https://github/a/b/wiki/Test Page">https://github/a/b/wiki/Test Page</a>',
+            f('<a href="https://github/a/b/wiki/Test Page">https://github/a/b/wiki/Test Page</a>',
               prefix, new),
-            u'<a href="/p/test/wiki/Test Page">/p/test/wiki/Test Page</a>')
+            '<a href="/p/test/wiki/Test Page">/p/test/wiki/Test Page</a>')
         assert_equal(
-            f(u'<a href="https://github/a/b/wiki/Test Page">Test blah blah</a>',
+            f('<a href="https://github/a/b/wiki/Test Page">Test blah blah</a>',
               prefix, new),
-            u'<a href="/p/test/wiki/Test Page">Test blah blah</a>')
+            '<a href="/p/test/wiki/Test Page">Test blah blah</a>')
         assert_equal(
-            f(u'<a href="https://github/a/b/wiki/Test Page">Test <b>Page</b></a>',
+            f('<a href="https://github/a/b/wiki/Test Page">Test <b>Page</b></a>',
               prefix, new),
-            u'<a href="/p/test/wiki/Test Page">Test <b>Page</b></a>')
+            '<a href="/p/test/wiki/Test Page">Test <b>Page</b></a>')
 
     @skipif(module_not_available('html2text'))
     def test_convert_markup_with_mediawiki2markdown(self):
@@ -407,7 +408,7 @@ Our website is [[http://domain.net]].
         importer.app = Mock()
         importer.app.url = '/p/test/wiki/'
         f = importer.convert_markup
-        source = u'''
+        source = '''
 ''Al'fredas 235 BC''
 == See also ==
 * [https://github.com/a/b/wiki/AgentSpring-running-instructions-for-d13n-model Test1]
@@ -415,7 +416,7 @@ Our website is [[http://domain.net]].
 * [https://github.com/a/b/wiki/AgentSpring-Q&A Test3]
 * [https://github.com/a/b/wiki/Extensions Test4]'''
 
-        result = u'''_Al'fredas 235 BC_
+        result = '''_Al'fredas 235 BC_
 
 ## See also
 
@@ -434,7 +435,7 @@ Our website is [[http://domain.net]].
         importer.app = Mock()
         importer.app.url = '/p/test/wiki/'
         f = importer.convert_markup
-        source = u'''h1. Header 1
+        source = '''h1. Header 1
 
 Some text 1.
 
@@ -442,7 +443,7 @@ h2. Header 2
 
 See [[Page]]'''
 
-        result = u'''# Header 1
+        result = '''# Header 1
 
 Some text 1.
 
@@ -458,8 +459,8 @@ See [Page]'''
         importer.app = Mock()
         importer.app.url = '/p/test/wiki/'
         f = importer.convert_markup
-        source = u'[[Ticks & Leeches]]'
-        result = u'[Ticks & Leeches]'
+        source = '[[Ticks & Leeches]]'
+        result = '[Ticks & Leeches]'
         # markdown should be untouched
         assert_equal(f(source, 'test.rst').strip(), result)
 
@@ -472,13 +473,13 @@ See [Page]'''
         f = importer.convert_markup
 
         # check if lists converting works properly
-        source = u'''There are good reasons for this:
+        source = '''There are good reasons for this:
 
   # Duplicate libraries regularly break builds
   # Subtle bugs emerge with duplicate libraries, and to a lesser extent, duplicate tools
   # We want you to try harder to make your formula work with what OS X comes with
 '''
-        result = u'''There are good reasons for this:
+        result = '''There are good reasons for this:
 
   1. Duplicate libraries regularly break builds
   2. Subtle bugs emerge with duplicate libraries, and to a lesser extent, duplicate tools
@@ -493,13 +494,13 @@ See [Page]'''
         assert_equal(f(source, 'test2.textile'), result)
 
         # links with formatting converts normal in textile now
-        source = u'''*[[this checklist|Troubleshooting]]*
+        source = '''*[[this checklist|Troubleshooting]]*
 
 some text and *[[Tips n' Tricks]]*
 
 *[[link|http://otherlink.com]]*
 '''
-        result = u'''**[this checklist](Troubleshooting)**
+        result = '''**[this checklist](Troubleshooting)**
 
 some text and **[Tips n\u2019 Tricks]**
 
@@ -514,9 +515,9 @@ some text and **[Tips n\u2019 Tricks]**
         importer.app = Mock()
         importer.app.url = '/p/test/wiki/'
         f = importer.convert_markup
-        source = u'*[[this checklist|Troubleshooting]]*'
+        source = '*[[this checklist|Troubleshooting]]*'
         assert_equal(f(source, 't.textile').strip(),
-                     u'**[this checklist](Troubleshooting)**')
+                     '**[this checklist](Troubleshooting)**')
 
     @without_module('html2text')
     def test_convert_textile_special_tag_without_html2text(self):
@@ -525,8 +526,8 @@ some text and **[Tips n\u2019 Tricks]**
         importer.app = Mock()
         importer.app.url = '/p/test/wiki/'
         f = importer.convert_markup
-        source = u'*[[this checklist|Troubleshooting]]*'
-        result = u'<p><strong>[[this checklist|Troubleshooting]]</strong></p>'
+        source = '*[[this checklist|Troubleshooting]]*'
+        result = '<p><strong>[[this checklist|Troubleshooting]]</strong></p>'
         assert_equal(f(source, 't.textile').strip(), result)
 
     @patch('forgeimporters.github.wiki.mkdtemp', autospec=True)
@@ -575,11 +576,11 @@ class TestGitHubWikiImportController(TestController, TestCase):
         self.assertEqual(r.location, 'http://localhost/p/%s/admin/' %
                          test_project_with_wiki)
         args = import_tool.post.call_args[1]
-        self.assertEqual(u'GitHub Wiki', args['mount_label'])
-        self.assertEqual(u'gh-wiki', args['mount_point'])
-        self.assertEqual(u'mulder', args['project_name'])
-        self.assertEqual(u'spooky', args['user_name'])
-        self.assertEqual(u'import_history', args['tool_option'])
+        self.assertEqual('GitHub Wiki', args['mount_label'])
+        self.assertEqual('gh-wiki', args['mount_point'])
+        self.assertEqual('mulder', args['project_name'])
+        self.assertEqual('spooky', args['user_name'])
+        self.assertEqual('import_history', args['tool_option'])
         self.assertEqual(requests.head.call_count, 1)
 
     @with_wiki
@@ -597,11 +598,11 @@ class TestGitHubWikiImportController(TestController, TestCase):
         self.assertEqual(r.location, 'http://localhost/p/%s/admin/' %
                          test_project_with_wiki)
         args = import_tool.post.call_args[1]
-        self.assertEqual(u'GitHub Wiki', args['mount_label'])
-        self.assertEqual(u'gh-wiki', args['mount_point'])
-        self.assertEqual(u'mulder', args['project_name'])
-        self.assertEqual(u'spooky', args['user_name'])
-        self.assertEqual(u'', args['tool_option'])
+        self.assertEqual('GitHub Wiki', args['mount_label'])
+        self.assertEqual('gh-wiki', args['mount_point'])
+        self.assertEqual('mulder', args['project_name'])
+        self.assertEqual('spooky', args['user_name'])
+        self.assertEqual('', args['tool_option'])
         self.assertEqual(requests.head.call_count, 1)
 
     @with_wiki
diff --git a/ForgeImporters/forgeimporters/github/tracker.py b/ForgeImporters/forgeimporters/github/tracker.py
index 1a915bc..23c3fff 100644
--- a/ForgeImporters/forgeimporters/github/tracker.py
+++ b/ForgeImporters/forgeimporters/github/tracker.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import re
 import logging
 from datetime import datetime
@@ -157,7 +158,7 @@ class GitHubTrackerImporter(ToolImporter):
         return datetime.strptime(datetime_string, '%Y-%m-%dT%H:%M:%SZ')
 
     def get_user_link(self, user):
-        return u'[{0}](https://github.com/{0})'.format(user)
+        return '[{0}](https://github.com/{0})'.format(user)
 
     def process_fields(self, extractor, ticket, issue):
         ticket.summary = issue['title']
@@ -173,10 +174,10 @@ class GitHubTrackerImporter(ToolImporter):
         body, attachments = self._get_attachments(extractor, issue['body'])
         ticket.add_multiple_attachments(attachments)
         ticket.description = (
-            u'*Originally created by:* {creator}\n'
-            u'{owner}'
-            u'\n'
-            u'{body}').format(
+            '*Originally created by:* {creator}\n'
+            '{owner}'
+            '\n'
+            '{body}').format(
             creator=self.get_user_link(issue['user']['login']),
             owner=owner_line,
             body=self.github_markdown_converter.convert(body),
@@ -188,7 +189,7 @@ class GitHubTrackerImporter(ToolImporter):
             body, attachments = self._get_attachments(
                 extractor, comment['body'])
             if comment['user']:
-                posted_by = u'*Originally posted by:* {}\n\n'.format(
+                posted_by = '*Originally posted by:* {}\n\n'.format(
                     self.get_user_link(comment['user']['login']))
                 body = posted_by + body
             p = ticket.discussion_thread.add_post(
diff --git a/ForgeImporters/forgeimporters/github/utils.py b/ForgeImporters/forgeimporters/github/utils.py
index 3f00310..edecb1b 100644
--- a/ForgeImporters/forgeimporters/github/utils.py
+++ b/ForgeImporters/forgeimporters/github/utils.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import re
 
 
@@ -22,7 +23,7 @@ class GitHubMarkdownConverter(object):
 
     def __init__(self, gh_user, gh_project):
         self.gh_project = '%s/%s' % (gh_user, gh_project)
-        self.gh_base_url = u'https://github.com/'
+        self.gh_base_url = 'https://github.com/'
         self.code_patterns = ['```', '~~~']
 
     def convert(self, text):
@@ -110,10 +111,10 @@ class GitHubMarkdownConverter(object):
         return text
 
     def _gh_commit_url(self, project, sha, title):
-        return u'[%s](%s)' % (title, self.gh_base_url + project + '/commit/' + sha)
+        return '[%s](%s)' % (title, self.gh_base_url + project + '/commit/' + sha)
 
     def _gh_ticket_url(self, project, tid, title):
-        return u'[%s](%s)' % (title, self.gh_base_url + project + '/issues/' + str(tid))
+        return '[%s](%s)' % (title, self.gh_base_url + project + '/issues/' + str(tid))
 
     def _convert_sha(self, m):
         return '%s[%s]%s' % (m.group(1), m.group(2)[:6], m.group(3))
diff --git a/ForgeImporters/forgeimporters/github/wiki.py b/ForgeImporters/forgeimporters/github/wiki.py
index 220eef3..b1f7a38 100644
--- a/ForgeImporters/forgeimporters/github/wiki.py
+++ b/ForgeImporters/forgeimporters/github/wiki.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import re
 from datetime import datetime
@@ -69,7 +70,7 @@ log = logging.getLogger(__name__)
 class GitHubWikiImportForm(ToolImportForm):
     gh_project_name = GitHubProjectNameValidator()
     gh_user_name = fev.UnicodeString(not_empty=True)
-    tool_option = fev.UnicodeString(if_missing=u'')
+    tool_option = fev.UnicodeString(if_missing='')
 
 
 class GitHubWikiImportController(ToolImportController, GitHubOAuthMixin):
@@ -390,12 +391,12 @@ class GitHubWikiImporter(ToolImporter):
 
     def _gollum_external_link(self, link, title, options):
         if title:
-            return u'[{}]({})'.format(title, link)
-        return u'<{}>'.format(link)
+            return '[{}]({})'.format(title, link)
+        return '<{}>'.format(link)
 
     def _gollum_page_link(self, link, title, options):
         page = self._convert_page_name(link)
-        page = page.replace(u'&amp;', u'&')  # allow & in page links
+        page = page.replace('&amp;', '&')  # allow & in page links
         # gollum page lookups are case-insensitive, you'll always get link to
         # whatever comes first in the file system, no matter how you refer to a page.
         # E.g. if you have two pages: a.md and A.md both [[a]] and [[A]] will refer a.md.
@@ -409,8 +410,8 @@ class GitHubWikiImporter(ToolImporter):
             page = self.available_pages[idx]
 
         if title:
-            return u'[{}]({})'.format(title, page)
-        return u'[{}]'.format(page)
+            return '[{}]({})'.format(title, page)
+        return '[{}]'.format(page)
 
     def rewrite_links(self, html, prefix, new_prefix):
         if not prefix.endswith('/'):
diff --git a/ForgeImporters/forgeimporters/tests/forge/test_tracker.py b/ForgeImporters/forgeimporters/tests/forge/test_tracker.py
index 9be7743..99a098c 100644
--- a/ForgeImporters/forgeimporters/tests/forge/test_tracker.py
+++ b/ForgeImporters/forgeimporters/tests/forge/test_tracker.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from datetime import datetime
 from unittest import TestCase
 
@@ -365,9 +366,9 @@ class TestForgeTrackerImportController(TestController, TestCase):
         self.assertEqual(r.location, 'http://localhost/p/test/admin/')
         sui.assert_called_once_with(project, 'tickets.json', '{"key": "val"}')
         self.assertEqual(
-            u'mymount', import_tool.post.call_args[1]['mount_point'])
+            'mymount', import_tool.post.call_args[1]['mount_point'])
         self.assertEqual(
-            u'mylabel', import_tool.post.call_args[1]['mount_label'])
+            'mylabel', import_tool.post.call_args[1]['mount_label'])
 
     @with_tracker
     @mock.patch('forgeimporters.forge.tracker.save_importer_upload')
diff --git a/ForgeImporters/forgeimporters/tests/github/functional/test_github.py b/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
index c4d2bce..bfada9e 100644
--- a/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
+++ b/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
@@ -14,6 +14,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 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 d91c25b..f4106aa 100644
--- a/ForgeImporters/forgeimporters/tests/github/test_extractor.py
+++ b/ForgeImporters/forgeimporters/tests/github/test_extractor.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import json
 from unittest import TestCase
 import urllib2
@@ -35,28 +36,28 @@ class TestGitHubProjectExtractor(TestCase):
         'has_wiki': True,
     }
     CLOSED_ISSUES_LIST = [
-        {u'number': 1},
-        {u'number': 2},
+        {'number': 1},
+        {'number': 2},
     ]
     OPENED_ISSUES_LIST = [
-        {u'number': 3},
-        {u'number': 4},
-        {u'number': 5},
+        {'number': 3},
+        {'number': 4},
+        {'number': 5},
     ]
     OPENED_ISSUES_LIST_PAGE2 = [
-        {u'number': 6},
-        {u'number': 7},
-        {u'number': 8},
+        {'number': 6},
+        {'number': 7},
+        {'number': 8},
     ]
-    ISSUE_COMMENTS = [u'hello', u'mocked_comment']
-    ISSUE_COMMENTS_PAGE2 = [u'hello2', u'mocked_comment2']
+    ISSUE_COMMENTS = ['hello', 'mocked_comment']
+    ISSUE_COMMENTS_PAGE2 = ['hello2', 'mocked_comment2']
     ISSUE_EVENTS = [
-        {u'event': u'closed'},
-        {u'event': u'reopened'},
+        {'event': 'closed'},
+        {'event': 'reopened'},
     ]
     ISSUE_EVENTS_PAGE2 = [
-        {u'event': u'assigned'},
-        {u'event': u'not-supported-event'},
+        {'event': 'assigned'},
+        {'event': 'not-supported-event'},
     ]
 
     def mocked_urlopen(self, url):
diff --git a/ForgeImporters/forgeimporters/tests/github/test_tasks.py b/ForgeImporters/forgeimporters/tests/github/test_tasks.py
index b048407..98effbd 100644
--- a/ForgeImporters/forgeimporters/tests/github/test_tasks.py
+++ b/ForgeImporters/forgeimporters/tests/github/test_tasks.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 da6460b..47af12d 100644
--- a/ForgeImporters/forgeimporters/tests/github/test_tracker.py
+++ b/ForgeImporters/forgeimporters/tests/github/test_tracker.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from datetime import datetime
 from unittest import TestCase
 from urllib2 import HTTPError
@@ -124,9 +125,9 @@ class TestTrackerImporter(TestCase):
                 'label': 'Milestone',
                 'milestones': [
                         {'name': 'first', 'due_date':
-                            u'2015-04-23', 'complete': False},
+                            '2015-04-23', 'complete': False},
                     {'name': 'second', 'due_date':
-                     u'2015-04-25', 'complete': False},
+                     '2015-04-25', 'complete': False},
                 ],
             },
         ])
diff --git a/ForgeImporters/forgeimporters/tests/test_base.py b/ForgeImporters/forgeimporters/tests/test_base.py
index cb96ed2..14a38b8 100644
--- a/ForgeImporters/forgeimporters/tests/test_base.py
+++ b/ForgeImporters/forgeimporters/tests/test_base.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from unittest import TestCase
 import errno
 
diff --git a/ForgeImporters/forgeimporters/trac/__init__.py b/ForgeImporters/forgeimporters/trac/__init__.py
index fa733a6..dafc543 100644
--- a/ForgeImporters/forgeimporters/trac/__init__.py
+++ b/ForgeImporters/forgeimporters/trac/__init__.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from formencode import validators as fev
 import requests
 
diff --git a/ForgeImporters/forgeimporters/trac/project.py b/ForgeImporters/forgeimporters/trac/project.py
index 0f44259..25c3f43 100644
--- a/ForgeImporters/forgeimporters/trac/project.py
+++ b/ForgeImporters/forgeimporters/trac/project.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 b6a640c..c8237cd 100644
--- a/ForgeImporters/forgeimporters/trac/tests/functional/test_trac.py
+++ b/ForgeImporters/forgeimporters/trac/tests/functional/test_trac.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 1e98584..005f9f2 100644
--- a/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
+++ b/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import json
 import os
 
@@ -140,12 +141,12 @@ class TestTracTicketImportController(TestController, TestCase):
                           status=302)
         self.assertEqual(r.location, 'http://localhost/p/test/admin/')
         self.assertEqual(
-            u'mymount', import_tool.post.call_args[1]['mount_point'])
+            'mymount', import_tool.post.call_args[1]['mount_point'])
         self.assertEqual(
-            u'mylabel', import_tool.post.call_args[1]['mount_label'])
+            'mylabel', import_tool.post.call_args[1]['mount_label'])
         self.assertEqual('{"orig_user": "new_user"}',
                          import_tool.post.call_args[1]['user_map'])
-        self.assertEqual(u'http://example.com/trac/url/',
+        self.assertEqual('http://example.com/trac/url/',
                          import_tool.post.call_args[1]['trac_url'])
 
     @with_tracker
diff --git a/ForgeImporters/forgeimporters/trac/tickets.py b/ForgeImporters/forgeimporters/trac/tickets.py
index 50c867a..ebdc60a 100644
--- a/ForgeImporters/forgeimporters/trac/tickets.py
+++ b/ForgeImporters/forgeimporters/trac/tickets.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import json
 import re
 
diff --git a/ForgeImporters/setup.py b/ForgeImporters/setup.py
index 2ad2726..21c9d91 100644
--- a/ForgeImporters/setup.py
+++ b/ForgeImporters/setup.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from setuptools import setup, find_packages
 
 
diff --git a/ForgeLink/forgelink/link_main.py b/ForgeLink/forgelink/link_main.py
index dbe6858..5e4af9d 100644
--- a/ForgeLink/forgelink/link_main.py
+++ b/ForgeLink/forgelink/link_main.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 # -*- python -*-
+from __future__ import unicode_literals
 import logging
 import json
 
diff --git a/ForgeLink/forgelink/tests/functional/test_rest.py b/ForgeLink/forgelink/tests/functional/test_rest.py
index b2ac3b3..9678042 100644
--- a/ForgeLink/forgelink/tests/functional/test_rest.py
+++ b/ForgeLink/forgelink/tests/functional/test_rest.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from nose.tools import assert_equal
 from allura.tests import decorators as td
 from alluratest.controller import TestRestApiBase
@@ -35,20 +36,20 @@ class TestLinkApi(TestRestApiBase):
         h.set_context('test', 'link', neighborhood='Projects')
 
     def test_rest_link(self):
-        r = self.api_get(u'/rest/p/test/link'.encode('utf-8'))
+        r = self.api_get('/rest/p/test/link'.encode('utf-8'))
         assert_equal(r.json['url'], None)
 
-        r = self.api_post(u'/rest/p/test/link'.encode('utf-8'),
+        r = self.api_post('/rest/p/test/link'.encode('utf-8'),
                           url='http://google.com')
         assert_equal(r.json['url'], 'http://google.com')
 
-        self.api_post(u'/rest/p/test/link'.encode('utf-8'),
+        self.api_post('/rest/p/test/link'.encode('utf-8'),
                       url='http://yahoo.com')
-        r = self.api_get(u'/rest/p/test/link'.encode('utf-8'))
+        r = self.api_get('/rest/p/test/link'.encode('utf-8'))
         assert_equal(r.json['url'], 'http://yahoo.com')
 
-        self.api_post(u'/rest/p/test/link'.encode('utf-8'))
-        r = self.api_get(u'/rest/p/test/link'.encode('utf-8'))
+        self.api_post('/rest/p/test/link'.encode('utf-8'))
+        r = self.api_get('/rest/p/test/link'.encode('utf-8'))
         assert_equal(r.json['url'], 'http://yahoo.com')
 
     def test_rest_link_get_permissions(self):
@@ -76,7 +77,7 @@ class TestLinkApi(TestRestApiBase):
                       params={'url': 'http://yahoo.com'},
                       extra_environ={'username': '*anonymous'},
                       status=200)
-        r = self.api_get(u'/rest/p/test/link'.encode('utf-8'))
+        r = self.api_get('/rest/p/test/link'.encode('utf-8'))
         assert_equal(r.json['url'], 'http://yahoo.com')
 
 
diff --git a/ForgeLink/forgelink/tests/functional/test_root.py b/ForgeLink/forgelink/tests/functional/test_root.py
index 0167fda..ad82051 100644
--- a/ForgeLink/forgelink/tests/functional/test_root.py
+++ b/ForgeLink/forgelink/tests/functional/test_root.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import json
 
 from nose.tools import assert_equal, assert_in
@@ -136,7 +137,7 @@ class TestConfigOptions(TestController):
                           menu_item['admin_options'])
                 break
         else:
-            raise AssertionError(u"Didn't find 'link' tool in {}".format(admin_nav_data['menu']))
+            raise AssertionError("Didn't find 'link' tool in {}".format(admin_nav_data['menu']))
 
     @td.with_link
     def test_menu_configurable(self):
diff --git a/ForgeLink/forgelink/tests/test_app.py b/ForgeLink/forgelink/tests/test_app.py
index 2976341..4950f20 100644
--- a/ForgeLink/forgelink/tests/test_app.py
+++ b/ForgeLink/forgelink/tests/test_app.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import tempfile
 import json
 
diff --git a/ForgeLink/forgelink/version.py b/ForgeLink/forgelink/version.py
index 1b493f8..192acec 100644
--- a/ForgeLink/forgelink/version.py
+++ b/ForgeLink/forgelink/version.py
@@ -15,5 +15,6 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeLink/setup.py b/ForgeLink/setup.py
index fc91792..7e10d92 100644
--- a/ForgeLink/setup.py
+++ b/ForgeLink/setup.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from setuptools import setup, find_packages
 
 from forgelink.version import __version__
diff --git a/ForgeSVN/forgesvn/controllers.py b/ForgeSVN/forgesvn/controllers.py
index 8a13c7a..b8cdbd6 100644
--- a/ForgeSVN/forgesvn/controllers.py
+++ b/ForgeSVN/forgesvn/controllers.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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/svn.py b/ForgeSVN/forgesvn/model/svn.py
index 0e8a2d0..fdf7bf1 100644
--- a/ForgeSVN/forgesvn/model/svn.py
+++ b/ForgeSVN/forgesvn/model/svn.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import re
 import os
 import shutil
diff --git a/ForgeSVN/forgesvn/svn_main.py b/ForgeSVN/forgesvn/svn_main.py
index 8c97630..24ee714 100644
--- a/ForgeSVN/forgesvn/svn_main.py
+++ b/ForgeSVN/forgesvn/svn_main.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 #-*- python -*-
+from __future__ import unicode_literals
 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 d152a9e..172a607 100644
--- a/ForgeSVN/forgesvn/tests/__init__.py
+++ b/ForgeSVN/forgesvn/tests/__init__.py
@@ -19,6 +19,7 @@
 
 
 # Make our own SVN tool test decorator
+from __future__ import unicode_literals
 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 7394c1b..b7b350a 100644
--- a/ForgeSVN/forgesvn/tests/functional/test_auth.py
+++ b/ForgeSVN/forgesvn/tests/functional/test_auth.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 3824e71..91291b4 100644
--- a/ForgeSVN/forgesvn/tests/functional/test_controllers.py
+++ b/ForgeSVN/forgesvn/tests/functional/test_controllers.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import json
 import shutil
 import os
@@ -229,12 +230,12 @@ class TestRootController(SVNTestController):
         shutil.rmtree(c.app.repo.tarball_path, ignore_errors=True)
         r = self.app.get('/p/test/svn-tags/19/tree/')
         form = r.html.find('form', 'tarball')
-        assert_equal(form.button.text, u'\xa0Download Snapshot')
+        assert_equal(form.button.text, '\xa0Download Snapshot')
         assert_equal(form.get('action'), '/p/test/svn-tags/19/tarball')
 
         r = self.app.get('/p/test/svn-tags/19/tree/tags/tag-1.0/')
         form = r.html.find('form', 'tarball')
-        assert_equal(form.button.text, u'\xa0Download Snapshot')
+        assert_equal(form.button.text, '\xa0Download Snapshot')
         assert_equal(form.get('action'), '/p/test/svn-tags/19/tarball')
         assert_equal(form.find('input', attrs=dict(name='path')).get('value'), '/tags/tag-1.0')
 
diff --git a/ForgeSVN/forgesvn/tests/model/test_repository.py b/ForgeSVN/forgesvn/tests/model/test_repository.py
index d4323f0..3135697 100644
--- a/ForgeSVN/forgesvn/tests/model/test_repository.py
+++ b/ForgeSVN/forgesvn/tests/model/test_repository.py
@@ -16,6 +16,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import shutil
 import unittest
@@ -241,83 +242,83 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
              'refs': ['HEAD'],
              'committed': {
                  'date': datetime(2013, 11, 8, 13, 38, 11, 152821),
-                 'name': u'coldmind', 'email': ''},
-             'message': u'',
+                 'name': 'coldmind', 'email': ''},
+             'message': '',
              'rename_details': {},
              'id': 6,
              'authored': {
                  'date': datetime(2013, 11, 8, 13, 38, 11, 152821),
-                 'name': u'coldmind',
+                 'name': 'coldmind',
                  'email': ''
              }, 'size': None},
             {'parents': [4],
              'refs': [],
              'committed': {
                  'date': datetime(2010, 11, 18, 20, 14, 21, 515743),
-                 'name': u'rick446',
+                 'name': 'rick446',
                  'email': ''},
-             'message': u'Copied a => b',
+             'message': 'Copied a => b',
              'rename_details': {},
              'id': 5,
              'authored': {
                  'date': datetime(2010, 11, 18, 20, 14, 21, 515743),
-                 'name': u'rick446',
+                 'name': 'rick446',
                  'email': ''},
              'size': None},
             {'parents': [3],
              'refs': [],
              'committed': {
                  'date': datetime(2010, 10, 8, 15, 32, 59, 383719),
-                 'name': u'rick446',
+                 'name': 'rick446',
                  'email': ''},
-             'message': u'Remove hello.txt',
+             'message': 'Remove hello.txt',
              'rename_details': {},
              'id': 4,
              'authored': {
                  'date': datetime(2010, 10, 8, 15, 32, 59, 383719),
-                 'name': u'rick446',
+                 'name': 'rick446',
                  'email': ''},
              'size': None},
             {'parents': [2],
              'refs': [],
              'committed': {
                  'date': datetime(2010, 10, 8, 15, 32, 48, 272296),
-                 'name': u'rick446',
+                 'name': 'rick446',
                  'email': ''},
-             'message': u'Modify readme',
+             'message': 'Modify readme',
              'rename_details': {},
              'id': 3,
              'authored':
              {'date': datetime(2010, 10, 8, 15, 32, 48, 272296),
-              'name': u'rick446',
+              'name': 'rick446',
               'email': ''},
              'size': None},
             {'parents': [1],
              'refs': [],
              'committed': {
                  'date': datetime(2010, 10, 8, 15, 32, 36, 221863),
-                 'name': u'rick446',
+                 'name': 'rick446',
                  'email': ''},
-             'message': u'Add path',
+             'message': 'Add path',
              'rename_details': {},
              'id': 2,
              'authored': {
                  'date': datetime(2010, 10, 8, 15, 32, 36, 221863),
-                 'name': u'rick446',
+                 'name': 'rick446',
                  'email': ''},
              'size': None},
             {'parents': [],
              'refs': [],
              'committed': {
                  'date': datetime(2010, 10, 8, 15, 32, 7, 238375),
-                 'name': u'rick446',
+                 'name': 'rick446',
                  'email': ''},
-             'message': u'Create readme',
+             'message': 'Create readme',
              'rename_details': {},
              'id': 1,
              'authored': {
                  'date': datetime(2010, 10, 8, 15, 32, 7, 238375),
-                 'name': u'rick446',
+                 'name': 'rick446',
                  'email': ''},
              'size': None}])
 
@@ -326,24 +327,24 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
         assert_equal(entries, [
             {'authored': {'date': datetime(2010, 10, 8, 15, 32, 48, 272296),
                           'email': '',
-                          'name': u'rick446'},
+                          'name': 'rick446'},
              'committed': {'date': datetime(2010, 10, 8, 15, 32, 48, 272296),
                            'email': '',
-                           'name': u'rick446'},
+                           'name': 'rick446'},
              'id': 3,
-             'message': u'Modify readme',
+             'message': 'Modify readme',
              'parents': [2],
              'refs': [],
              'size': 28,
              'rename_details': {}},
             {'authored': {'date': datetime(2010, 10, 8, 15, 32, 7, 238375),
                           'email': '',
-                          'name': u'rick446'},
+                          'name': 'rick446'},
              'committed': {'date': datetime(2010, 10, 8, 15, 32, 7, 238375),
                            'email': '',
-                           'name': u'rick446'},
+                           'name': 'rick446'},
              'id': 1,
-             'message': u'Create readme',
+             'message': 'Create readme',
              'parents': [],
              'refs': [],
              'size': 15,
@@ -404,7 +405,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
     def test_diff_copy(self):
         entry = self.repo.commit(self.repo.log(5, id_only=True, limit=1).next())
         assert_equals(dict(entry.diffs), dict(
-                copied=[{'new': u'/b', 'old': u'/a', 'ratio': 1}],  renamed=[],
+                copied=[{'new': '/b', 'old': '/a', 'ratio': 1}],  renamed=[],
                 changed=[], removed=[], added=[], total=1))
 
     def test_commit(self):
@@ -522,44 +523,44 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
             'after': 'r6',
             'before': 'r4',
             'commits': [{
-                'id': u'r6',
-                'url': u'http://localhost/p/test/src/6/',
+                'id': 'r6',
+                'url': 'http://localhost/p/test/src/6/',
                 'timestamp': datetime(2013, 11, 8, 13, 38, 11, 152000),
-                'message': u'',
-                'author': {'name': u'coldmind',
-                           'email': u'',
-                           'username': u''},
-                'committer': {'name': u'coldmind',
-                              'email': u'',
-                              'username': u''},
-                'added': [u'/ЗРЯЧИЙ_ТА_ПОБАЧИТЬ'],
+                'message': '',
+                'author': {'name': 'coldmind',
+                           'email': '',
+                           'username': ''},
+                'committer': {'name': 'coldmind',
+                              'email': '',
+                              'username': ''},
+                'added': ['/ЗРЯЧИЙ_ТА_ПОБАЧИТЬ'],
                 'removed': [],
                 'modified': [],
                 'copied': [],
                 'renamed': [],
             }, {
-                'id': u'r5',
-                'url': u'http://localhost/p/test/src/5/',
+                'id': 'r5',
+                'url': 'http://localhost/p/test/src/5/',
                 'timestamp': datetime(2010, 11, 18, 20, 14, 21, 515000),
-                'message': u'Copied a => b',
-                'author': {'name': u'rick446',
-                           'email': u'',
-                           'username': u''},
-                'committer': {'name': u'rick446',
-                              'email': u'',
-                              'username': u''},
+                'message': 'Copied a => b',
+                'author': {'name': 'rick446',
+                           'email': '',
+                           'username': ''},
+                'committer': {'name': 'rick446',
+                              'email': '',
+                              'username': ''},
                 'added': [],
                 'removed': [],
                 'modified': [],
                 'copied': [
-                    {'new': u'/b', 'old': u'/a', 'ratio': 1},
+                    {'new': '/b', 'old': '/a', 'ratio': 1},
                 ],
                 'renamed': [],
             }],
             'repository': {
-                'name': u'SVN',
-                'full_name': u'/p/test/src/',
-                'url': u'http://localhost/p/test/src/',
+                'name': 'SVN',
+                'full_name': '/p/test/src/',
+                'url': 'http://localhost/p/test/src/',
             },
         }
         assert_equals(payload, expected_payload)
@@ -635,11 +636,11 @@ class TestSVNRev(unittest.TestCase):
         ThreadLocalORMSession.flush_all()
         send_notifications(self.repo, [self.repo.rev_to_commit_id(1)])
         ThreadLocalORMSession.flush_all()
-        n = M.Notification.query.find({u'subject': u'[test:src] New commit [r1] by rick446'}).first()
+        n = M.Notification.query.find({'subject': '[test:src] New commit [r1] by rick446'}).first()
 
         assert n
-        assert_in(u'By rick446', n.text)
-        assert_in(u'Create readme', n.text)
+        assert_in('By rick446', n.text)
+        assert_in('Create readme', n.text)
 
 
 class _Test(unittest.TestCase):
@@ -816,8 +817,8 @@ class TestRepo(_TestWithRepo):
         notifications = M.Notification.query.find().all()
         for n in notifications:
             if '100 new commits' in n.subject:
-                assert_in(u'By Test Committer on 10/08/2010 15:32', n.text)
-                assert_in(u'http://localhost/ci/foo99/', n.text)
+                assert_in('By Test Committer on 10/08/2010 15:32', n.text)
+                assert_in('http://localhost/ci/foo99/', n.text)
                 break
         else:
             assert False, 'Did not find notification'
@@ -921,13 +922,13 @@ class TestCommit(_TestWithRepo):
     def test_diffs_file_renames(self):
         def open_blob(blob):
             blobs = {
-                u'a': u'Leia',
-                u'/b/a/a': u'Darth Vader',
-                u'/b/a/b': u'Luke Skywalker',
-                u'/b/b': u'Death Star will destroy you',
-                u'/b/c': u'Luke Skywalker',  # moved from /b/a/b
+                'a': 'Leia',
+                '/b/a/a': 'Darth Vader',
+                '/b/a/b': 'Luke Skywalker',
+                '/b/b': 'Death Star will destroy you',
+                '/b/c': 'Luke Skywalker',  # moved from /b/a/b
                 # moved from /b/b and modified
-                u'/b/a/z': u'Death Star will destroy you\nALL',
+                '/b/a/z': 'Death Star will destroy you\nALL',
             }
             from cStringIO import StringIO
             return StringIO(blobs.get(blob.path(), ''))
@@ -981,19 +982,19 @@ class TestCommit(_TestWithRepo):
         ci.parent_ids = ['bar']
         self._make_log(ci)
         self.repo._impl.paged_diffs.return_value = {
-            'added': [u'b/c', u'b/a/z'],
-            'removed': [u'/b/a/b', u'b/b'],
+            'added': ['b/c', 'b/a/z'],
+            'removed': ['/b/a/b', 'b/b'],
             'changed': [],
             'copied': [
                 {
-                    'new': u'b/c',
-                    'old': u'b/a/b',
+                    'new': 'b/c',
+                    'old': 'b/a/b',
                     'ratio': 1,
                     'diff': '',
                 },
                 {
-                    'new': u'b/a/z',
-                    'old': u'b/b',
+                    'new': 'b/a/z',
+                    'old': 'b/b',
                     'ratio': 1,
                     'diff': '',
                 },
@@ -1001,9 +1002,9 @@ class TestCommit(_TestWithRepo):
             'renamed': [],
             'total': 2
         }
-        assert_equal(ci.diffs.added, [u'b/a/z', u'b/c'])
+        assert_equal(ci.diffs.added, ['b/a/z', 'b/c'])
         assert_equal(ci.diffs.changed, [])
-        assert_equal(ci.diffs.removed, [u'/b/a/b', u'b/b'])
+        assert_equal(ci.diffs.removed, ['/b/a/b', 'b/b'])
         # see mock for open_blob
         assert_equal(len(ci.diffs.copied), 2)
         assert_equal(ci.diffs.copied[1]['old'], 'b/a/b')
@@ -1077,7 +1078,7 @@ class TestDirectRepoAccess(object):
     def test_paged_diffs(self):
         diffs = self.rev.diffs
         expected = {
-            'added': [u'/ЗРЯЧИЙ_ТА_ПОБАЧИТЬ'],
+            'added': ['/ЗРЯЧИЙ_ТА_ПОБАЧИТЬ'],
             'removed': [],
             'changed': [],
             'copied': [],
@@ -1089,7 +1090,7 @@ class TestDirectRepoAccess(object):
         _id = self.repo._impl._oid(2)
         diffs = self.repo.commit(_id).diffs
         expected = {
-            'added': [u'/a', u'/a/b', u'/a/b/c', u'/a/b/c/hello.txt'],
+            'added': ['/a', '/a/b', '/a/b/c', '/a/b/c/hello.txt'],
             'removed': [],
             'changed': [],
             'renamed': [],
@@ -1104,7 +1105,7 @@ class TestDirectRepoAccess(object):
             'added': [],
             'removed': [],
             'renamed': [],
-            'changed': [u'/README'],
+            'changed': ['/README'],
             'copied': [],
             'total': 1,
         }
diff --git a/ForgeSVN/forgesvn/tests/model/test_svnimplementation.py b/ForgeSVN/forgesvn/tests/model/test_svnimplementation.py
index 99fed05..9efaee7 100644
--- a/ForgeSVN/forgesvn/tests/model/test_svnimplementation.py
+++ b/ForgeSVN/forgesvn/tests/model/test_svnimplementation.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 a962424..a8d382b 100644
--- a/ForgeSVN/forgesvn/tests/test_svn_app.py
+++ b/ForgeSVN/forgesvn/tests/test_svn_app.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 2e0e99b..c041027 100644
--- a/ForgeSVN/forgesvn/tests/test_tasks.py
+++ b/ForgeSVN/forgesvn/tests/test_tasks.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import shutil
 import unittest
 import os
diff --git a/ForgeSVN/forgesvn/version.py b/ForgeSVN/forgesvn/version.py
index 1b493f8..192acec 100644
--- a/ForgeSVN/forgesvn/version.py
+++ b/ForgeSVN/forgesvn/version.py
@@ -15,5 +15,6 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeSVN/forgesvn/widgets.py b/ForgeSVN/forgesvn/widgets.py
index c0c880f..591174c 100644
--- a/ForgeSVN/forgesvn/widgets.py
+++ b/ForgeSVN/forgesvn/widgets.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import re
 
 import ew as ew_core
diff --git a/ForgeSVN/setup.py b/ForgeSVN/setup.py
index 40dcf73..0a0314a 100644
--- a/ForgeSVN/setup.py
+++ b/ForgeSVN/setup.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from setuptools import setup, find_packages
 
 from forgesvn.version import __version__
diff --git a/ForgeShortUrl/forgeshorturl/main.py b/ForgeShortUrl/forgeshorturl/main.py
index 66a5075..db01bf5 100644
--- a/ForgeShortUrl/forgeshorturl/main.py
+++ b/ForgeShortUrl/forgeshorturl/main.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 e8b0c29..b1c2559 100644
--- a/ForgeShortUrl/forgeshorturl/model/shorturl.py
+++ b/ForgeShortUrl/forgeshorturl/model/shorturl.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 d4aa712..059a348 100644
--- a/ForgeShortUrl/forgeshorturl/tests/functional/test.py
+++ b/ForgeShortUrl/forgeshorturl/tests/functional/test.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 0094402..a17086e 100644
--- a/ForgeShortUrl/forgeshorturl/widgets/short_url.py
+++ b/ForgeShortUrl/forgeshorturl/widgets/short_url.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from allura.lib.widgets import form_fields as ffw
 
 
diff --git a/ForgeShortUrl/setup.py b/ForgeShortUrl/setup.py
index 7450912..61a618b 100644
--- a/ForgeShortUrl/setup.py
+++ b/ForgeShortUrl/setup.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from setuptools import setup, find_packages
 
 
diff --git a/ForgeTracker/forgetracker/command/fix_discussion.py b/ForgeTracker/forgetracker/command/fix_discussion.py
index a0d090d..a85add1 100644
--- a/ForgeTracker/forgetracker/command/fix_discussion.py
+++ b/ForgeTracker/forgetracker/command/fix_discussion.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 c62d4c4..95b4eaf 100644
--- a/ForgeTracker/forgetracker/config/resources.py
+++ b/ForgeTracker/forgetracker/config/resources.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import pkg_resources
 
 
diff --git a/ForgeTracker/forgetracker/import_support.py b/ForgeTracker/forgetracker/import_support.py
index bc2aa73..c0f5f89 100644
--- a/ForgeTracker/forgetracker/import_support.py
+++ b/ForgeTracker/forgetracker/import_support.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 #-*- python -*-
+from __future__ import unicode_literals
 import logging
 import json
 from datetime import datetime
@@ -215,12 +216,12 @@ class ImportSupport(object):
             self.description_processing(remapped['description']))
         creator = owner = ''
         if ticket_dict.get('submitter') and not remapped.get('reported_by_id'):
-            creator = u'*Originally created by:* {0}\n'.format(
+            creator = '*Originally created by:* {0}\n'.format(
                 h.really_unicode(ticket_dict['submitter']))
         if ticket_dict.get('assigned_to') and not remapped.get('assigned_to_id'):
-            owner = u'*Originally owned by:* {0}\n'.format(
+            owner = '*Originally owned by:* {0}\n'.format(
                     h.really_unicode(ticket_dict['assigned_to']))
-        remapped['description'] = u'{0}{1}{2}{3}'.format(creator, owner,
+        remapped['description'] = '{0}{1}{2}{3}'.format(creator, owner,
                                                          '\n' if creator or owner else '', description)
 
         ticket_num = ticket_dict['id']
@@ -258,7 +259,7 @@ class ImportSupport(object):
         text = h.really_unicode(
             self.comment_processing(comment_dict['comment']))
         if not author_id and comment_dict['submitter']:
-            text = u'*Originally posted by:* {0}\n\n{1}'.format(
+            text = '*Originally posted by:* {0}\n\n{1}'.format(
                 h.really_unicode(comment_dict['submitter']), text)
         comment = thread.post(text=text, timestamp=ts)
         comment.author_id = author_id
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index a3b5f46..52563d7 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import urllib
 import json
@@ -84,7 +85,7 @@ SOLR_TYPE_DEFAULTS = dict(_b=False, _d=0)
 
 
 def get_default_for_solr_type(solr_type):
-    return SOLR_TYPE_DEFAULTS.get(solr_type, u'')
+    return SOLR_TYPE_DEFAULTS.get(solr_type, '')
 
 config = utils.ConfigProxy(
     common_suffix='forgemail.domain',
diff --git a/ForgeTracker/forgetracker/search.py b/ForgeTracker/forgetracker/search.py
index 86e46b4..088d9bf 100644
--- a/ForgeTracker/forgetracker/search.py
+++ b/ForgeTracker/forgetracker/search.py
@@ -14,6 +14,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 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 f9f36ce..69f552a 100644
--- a/ForgeTracker/forgetracker/site_stats.py
+++ b/ForgeTracker/forgetracker/site_stats.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from datetime import datetime, timedelta
 
 from bson import ObjectId
diff --git a/ForgeTracker/forgetracker/tasks.py b/ForgeTracker/forgetracker/tasks.py
index 5ad4214..d3217a0 100644
--- a/ForgeTracker/forgetracker/tasks.py
+++ b/ForgeTracker/forgetracker/tasks.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 8560556..161852e 100644
--- a/ForgeTracker/forgetracker/tests/command/test_fix_discussion.py
+++ b/ForgeTracker/forgetracker/tests/command/test_fix_discussion.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 b44a881..8dcd154 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_rest.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_rest.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 4456465..8a62959 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -16,6 +16,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 from datetime import datetime
 import urllib
 import os
@@ -577,12 +578,12 @@ class TestFunctionalController(TrackerTestController):
         r = self.app.get('/p/test/bugs/edit/')
         opts = r.html.find('select', attrs={'name': '_type'})
         opts = opts.findAll('option')
-        assert_equal(opts[0].get('value'), u'')
-        assert_equal(opts[0].getText(), u'no change')
-        assert_equal(opts[1].get('value'), u'Bug')
-        assert_equal(opts[1].getText(), u'Bug')
-        assert_equal(opts[2].get('value'), u'Feature Request')
-        assert_equal(opts[2].getText(), u'Feature Request')
+        assert_equal(opts[0].get('value'), '')
+        assert_equal(opts[0].getText(), 'no change')
+        assert_equal(opts[1].get('value'), 'Bug')
+        assert_equal(opts[1].getText(), 'Bug')
+        assert_equal(opts[2].get('value'), 'Feature Request')
+        assert_equal(opts[2].getText(), 'Feature Request')
 
     def test_mass_edit_private_field(self):
         kw = {'private': True}
@@ -781,7 +782,7 @@ class TestFunctionalController(TrackerTestController):
 
         # Make sure the 'Create Ticket' button is disabled for user without 'create' perm
         r = self.app.get('/bugs/', extra_environ=dict(username='*anonymous'))
-        create_button = r.html.find('a', attrs={'href': u'/p/test/bugs/new/'})
+        create_button = r.html.find('a', attrs={'href': '/p/test/bugs/new/'})
         assert_equal(create_button['class'], ['icon', 'sidebar-disabled'])
 
     def test_render_markdown_syntax(self):
@@ -794,8 +795,8 @@ class TestFunctionalController(TrackerTestController):
         # Create ticket
         params = dict(ticket_num=1,
                       app_config_id=c.app.config._id,
-                      summary=u'test md cache',
-                      description=u'# Test markdown cached_convert',
+                      summary='test md cache',
+                      description='# Test markdown cached_convert',
                       mod_date=datetime(2010, 1, 1, 1, 1, 1))
         ticket = tm.Ticket(**params)
 
@@ -842,12 +843,12 @@ class TestFunctionalController(TrackerTestController):
             'status': 'ccc',
             '_milestone': '',
             'assigned_to': '',
-            'labels': u'yellow,greén'.encode('utf-8'),
+            'labels': 'yellow,greén'.encode('utf-8'),
             'comment': ''
         })
         response = self.app.get('/bugs/1/')
         assert_true('yellow' in response)
-        assert_true(u'greén' in response)
+        assert_true('greén' in response)
         assert_true('<li><strong>labels</strong>:  --&gt; yellow, greén</li>' in response)
         self.app.post('/bugs/1/update_ticket', {
             'summary': 'zzz',
@@ -1136,9 +1137,9 @@ class TestFunctionalController(TrackerTestController):
             '/admin/bugs/set_custom_fields',
             params=variable_encode(params))
         r = self.app.get('/bugs/new/')
-        assert u'<option value="oné">oné</option>'.encode('utf-8') in r
-        assert u'<option value="one and á half">one and á half</option>'.encode('utf-8') in r
-        assert u'<option value="two">two</option>' in r
+        assert '<option value="oné">oné</option>'.encode('utf-8') in r
+        assert '<option value="one and á half">one and á half</option>'.encode('utf-8') in r
+        assert '<option value="two">two</option>' in r
 
     def test_select_custom_field_invalid_quotes(self):
         params = dict(
@@ -1153,9 +1154,9 @@ class TestFunctionalController(TrackerTestController):
             '/admin/bugs/set_custom_fields',
             params=variable_encode(params))
         r = self.app.get('/bugs/new/')
-        assert u'<option value="closéd">closéd</option>'.encode('utf-8') in r
-        assert u'<option value="quote">quote</option>' in r
-        assert u'<option value="missing">missing</option>' in r
+        assert '<option value="closéd">closéd</option>'.encode('utf-8') in r
+        assert '<option value="quote">quote</option>' in r
+        assert '<option value="missing">missing</option>' in r
 
     def test_custom_field_update_comments(self):
         params = dict(
@@ -1661,7 +1662,7 @@ class TestFunctionalController(TrackerTestController):
         assert_false('test third ticket' in str(ticket_rows))
 
     def test_new_ticket_notification_contains_attachments(self):
-        file_name = u'tést_root.py'.encode('utf-8')
+        file_name = 'tést_root.py'.encode('utf-8')
         file_data = file(__file__).read()
         upload = ('ticket_form.attachment', file_name, file_data)
         r = self.app.post('/bugs/save_ticket', {
@@ -1675,9 +1676,9 @@ class TestFunctionalController(TrackerTestController):
             dict(task_name='allura.tasks.mail_tasks.sendmail')
         ).first()
         expected_text = (
-            u'**Attachments:**\n\n'
-            u'- [tést_root.py]'
-            u'(http://localhost/p/test/bugs/1/attachment/t%C3%A9st_root.py)')
+            '**Attachments:**\n\n'
+            '- [tést_root.py]'
+            '(http://localhost/p/test/bugs/1/attachment/t%C3%A9st_root.py)')
         assert_in(expected_text, email.kwargs['text'])
 
     def test_ticket_notification_contains_milestones(self):
@@ -1788,9 +1789,9 @@ class TestFunctionalController(TrackerTestController):
 - **Status**: unread --> accepted
 - **Milestone**: 1.0 --> 2.0
 '''
-        email = u'\n'.join([email_header, first_ticket_changes, ''])
+        email = '\n'.join([email_header, first_ticket_changes, ''])
         assert_equal(email, first_user_email.kwargs.text)
-        email = u'\n'.join([email_header, second_ticket_changes, ''])
+        email = '\n'.join([email_header, second_ticket_changes, ''])
         assert_equal(email, second_user_email.kwargs.text)
         assert_in(email_header, admin_email.kwargs.text)
         assert_in(first_ticket_changes, admin_email.kwargs.text)
@@ -2029,7 +2030,7 @@ class TestFunctionalController(TrackerTestController):
         ticket_url = r.headers['Location']
         r = self.app.get(ticket_url, extra_environ=dict(username='*anonymous'))
         a = r.html.find('a', {'class': 'icon edit_ticket'})
-        assert_equal(a.text, u'\xa0Edit')
+        assert_equal(a.text, '\xa0Edit')
 
     def test_ticket_creator_cant_edit_private_ticket_without_update_perm(self):
         p = M.Project.query.get(shortname='test')
@@ -3357,9 +3358,9 @@ class TestArtifactLinks(TrackerTestController):
         assert_equal(ticket_features.app.config._id, features.config._id)
 
         c.app = bugs
-        link = u'<div class="markdown_content"><p><a class="alink" href="/p/test/bugs/1/">[#1]</a></p></div>'
+        link = '<div class="markdown_content"><p><a class="alink" href="/p/test/bugs/1/">[#1]</a></p></div>'
         assert_equal(g.markdown.convert('[#1]'), link)
 
         c.app = features
-        link = u'<div class="markdown_content"><p><a class="alink" href="/p/test/features/1/">[#1]</a></p></div>'
+        link = '<div class="markdown_content"><p><a class="alink" href="/p/test/features/1/">[#1]</a></p></div>'
         assert_equal(g.markdown.convert('[#1]'), link)
diff --git a/ForgeTracker/forgetracker/tests/test_app.py b/ForgeTracker/forgetracker/tests/test_app.py
index 9128d30..b349988 100644
--- a/ForgeTracker/forgetracker/tests/test_app.py
+++ b/ForgeTracker/forgetracker/tests/test_app.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 242646c..2cc33cd 100644
--- a/ForgeTracker/forgetracker/tests/test_tracker_roles.py
+++ b/ForgeTracker/forgetracker/tests/test_tracker_roles.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 1ef9b92..7065226 100644
--- a/ForgeTracker/forgetracker/tests/unit/__init__.py
+++ b/ForgeTracker/forgetracker/tests/unit/__init__.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 d1daad3..93ecf32 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_globals_model.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_globals_model.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 e7c36c5..579b805 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_milestone_controller.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_milestone_controller.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 
+from __future__ import unicode_literals
 from mock import Mock
 from nose.tools import assert_equal
 
@@ -29,7 +30,7 @@ from forgetracker.tracker_main import MilestoneController
 def test_unicode_lookup():
     # can't use name= in constructor, that's special attribute for Mock
     milestone = Mock()
-    milestone.name = u'Перспектива'
+    milestone.name = 'Перспектива'
     milestone_field = Mock(milestones=[milestone])
     milestone_field.name = '_milestone'
 
@@ -43,4 +44,4 @@ def test_unicode_lookup():
         mc = MilestoneController(root, field, milestone_urlparam)
 
     assert mc.milestone  # check that it is found
-    assert_equal(mc.milestone.name, u'Перспектива')
+    assert_equal(mc.milestone.name, 'Перспектива')
diff --git a/ForgeTracker/forgetracker/tests/unit/test_root_controller.py b/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
index c7bef18..fe8c304 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 e991c28..421a780 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_search.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_search.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 60576d1..b97a4c8 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_ticket_custom_fields_form.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_ticket_custom_fields_form.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 a11a088..982e801 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_ticket_form.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_ticket_form.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 99ba7de..55b5f18 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 f7f6c63..02cfbaf 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import re
 from datetime import datetime, timedelta
@@ -157,11 +158,11 @@ def get_change_text(name, new_value, old_value):
 def attachments_info(attachments):
     text = []
     for attach in attachments:
-        text.append(u"{} ({}; {})".format(
+        text.append("{} ({}; {})".format(
             h.really_unicode(attach.filename),
             h.do_filesizeformat(attach.length),
             attach.content_type))
-    return u"\n".join(text)
+    return "\n".join(text)
 
 
 def render_changes(changes, comment=None):
@@ -857,7 +858,7 @@ class RootController(BaseController, FeedController):
         response.headers['Content-Type'] = ''
         response.content_type = 'application/xml'
         d = dict(title='Ticket search results', link=h.absurl(c.app.url),
-                 description='You searched for %s' % q, language=u'en')
+                 description='You searched for %s' % q, language='en')
         if request.environ['PATH_INFO'].endswith('.atom'):
             feed = FG.Atom1Feed(**d)
         else:
@@ -939,7 +940,7 @@ class RootController(BaseController, FeedController):
             self.rate_limit(TM.Ticket, 'Ticket creation', redir='.')
             ticket = TM.Ticket.new(form_fields=ticket_form)
         ticket.update_fields_finish(ticket_form)
-        g.spam_checker.check(ticket_form['summary'] + u'\n' + ticket_form.get('description', ''), artifact=ticket,
+        g.spam_checker.check(ticket_form['summary'] + '\n' + ticket_form.get('description', ''), artifact=ticket,
                              user=c.user, content_type='ticket')
         c.app.globals.invalidate_bin_counts()
         notification_tasks.send_usermentions_notification.post(ticket.index_id(), ticket_form.get('description', ''))
@@ -1448,7 +1449,7 @@ class TicketController(BaseController, FeedController):
         require_access(self.ticket, 'update')
         old_text = self.ticket.description
         new_text = post_data.get('description', '')
-        g.spam_checker.check(post_data.get('summary', '') + u'\n' + post_data.get('description', ''),
+        g.spam_checker.check(post_data.get('summary', '') + '\n' + post_data.get('description', ''),
                              artifact=self.ticket, user=c.user, content_type='ticket')
         changes = changelog()
         comment = post_data.pop('comment', None)
diff --git a/ForgeTracker/forgetracker/version.py b/ForgeTracker/forgetracker/version.py
index 1b493f8..192acec 100644
--- a/ForgeTracker/forgetracker/version.py
+++ b/ForgeTracker/forgetracker/version.py
@@ -15,5 +15,6 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeTracker/forgetracker/widgets/admin.py b/ForgeTracker/forgetracker/widgets/admin.py
index 586ce6f..25ab534 100644
--- a/ForgeTracker/forgetracker/widgets/admin.py
+++ b/ForgeTracker/forgetracker/widgets/admin.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 19b55ec..04d1308 100644
--- a/ForgeTracker/forgetracker/widgets/admin_custom_fields.py
+++ b/ForgeTracker/forgetracker/widgets/admin_custom_fields.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 a62026e..bda0d78 100644
--- a/ForgeTracker/forgetracker/widgets/bin_form.py
+++ b/ForgeTracker/forgetracker/widgets/bin_form.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 64c0863..297bb33 100644
--- a/ForgeTracker/forgetracker/widgets/ticket_form.py
+++ b/ForgeTracker/forgetracker/widgets/ticket_form.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 cb6d989..cd6ebf1 100644
--- a/ForgeTracker/forgetracker/widgets/ticket_search.py
+++ b/ForgeTracker/forgetracker/widgets/ticket_search.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import ew as ew_core
 import ew.jinja2_ew as ew
 
diff --git a/ForgeTracker/setup.py b/ForgeTracker/setup.py
index d3e00cc..7837afb 100644
--- a/ForgeTracker/setup.py
+++ b/ForgeTracker/setup.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 8ab2db2..c885386 100644
--- a/ForgeUserStats/forgeuserstats/controllers/userstats.py
+++ b/ForgeUserStats/forgeuserstats/controllers/userstats.py
@@ -14,6 +14,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import unicode_literals
 from datetime import datetime
 import re
 
diff --git a/ForgeUserStats/forgeuserstats/main.py b/ForgeUserStats/forgeuserstats/main.py
index 580b3a6..0629d8b 100644
--- a/ForgeUserStats/forgeuserstats/main.py
+++ b/ForgeUserStats/forgeuserstats/main.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 #-*- python -*-
+from __future__ import unicode_literals
 import logging
 from tg import tmpl_context as c
 from datetime import datetime
diff --git a/ForgeUserStats/forgeuserstats/model/stats.py b/ForgeUserStats/forgeuserstats/model/stats.py
index 340f857..4ac9bd6 100644
--- a/ForgeUserStats/forgeuserstats/model/stats.py
+++ b/ForgeUserStats/forgeuserstats/model/stats.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 b9eff67..da5a5dd 100644
--- a/ForgeUserStats/forgeuserstats/tests/test_model.py
+++ b/ForgeUserStats/forgeuserstats/tests/test_model.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 aa08385..c858d78 100644
--- a/ForgeUserStats/forgeuserstats/tests/test_stats.py
+++ b/ForgeUserStats/forgeuserstats/tests/test_stats.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import pkg_resources
 import unittest
 
diff --git a/ForgeUserStats/forgeuserstats/version.py b/ForgeUserStats/forgeuserstats/version.py
index 1b493f8..192acec 100644
--- a/ForgeUserStats/forgeuserstats/version.py
+++ b/ForgeUserStats/forgeuserstats/version.py
@@ -15,5 +15,6 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeUserStats/forgeuserstats/widgets/forms.py b/ForgeUserStats/forgeuserstats/widgets/forms.py
index a807e8c..7b73715 100644
--- a/ForgeUserStats/forgeuserstats/widgets/forms.py
+++ b/ForgeUserStats/forgeuserstats/widgets/forms.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from allura.lib.widgets.forms import ForgeForm
 
 import ew as ew_core
diff --git a/ForgeUserStats/setup.py b/ForgeUserStats/setup.py
index 1ad5c3a..df68a2b 100644
--- a/ForgeUserStats/setup.py
+++ b/ForgeUserStats/setup.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from setuptools import setup, find_packages
 
 from forgeuserstats.version import __version__
diff --git a/ForgeWiki/forgewiki/converters.py b/ForgeWiki/forgewiki/converters.py
index c4fea2f..c4dd2f3 100644
--- a/ForgeWiki/forgewiki/converters.py
+++ b/ForgeWiki/forgewiki/converters.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 #-*- python -*-
+from __future__ import unicode_literals
 import re
 from bs4 import BeautifulSoup
 import six
diff --git a/ForgeWiki/forgewiki/model/wiki.py b/ForgeWiki/forgewiki/model/wiki.py
index a9240c3..2d1b71c 100644
--- a/ForgeWiki/forgewiki/model/wiki.py
+++ b/ForgeWiki/forgewiki/model/wiki.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 b06aa3d..9e804a7 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_rest.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_rest.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import json
 
 from nose.tools import assert_equal, assert_in, assert_not_equal
@@ -82,9 +83,9 @@ class TestWikiApi(TestRestApiBase):
             'text': 'Embrace the Dark Side',
             'labels': 'head hunting,dark side'
         }
-        r = self.api_post(u'/rest/p/test/wiki/tést/'.encode('utf-8'), **data)
+        r = self.api_post('/rest/p/test/wiki/tést/'.encode('utf-8'), **data)
         assert_equal(r.status_int, 200)
-        r = self.api_get(u'/rest/p/test/wiki/tést/'.encode('utf-8'))
+        r = self.api_get('/rest/p/test/wiki/tést/'.encode('utf-8'))
         assert_equal(r.json['text'], data['text'])
         assert_equal(r.json['labels'], data['labels'].split(','))
 
@@ -95,12 +96,12 @@ class TestWikiApi(TestRestApiBase):
         }
         # Set rate limit to unlimit
         with h.push_config(tg.config, **{'forgewiki.rate_limits': '{}'}):
-            r = self.api_post(u'/rest/p/test/wiki/page1/', status=200, **data)
+            r = self.api_post('/rest/p/test/wiki/page1/', status=200, **data)
             p = Page.query.get(title='page1')
             assert_not_equal(p, None)
         # Set rate limit to 1 in first hour of project
         with h.push_config(tg.config, **{'forgewiki.rate_limits': '{"3600": 1}'}):
-            r = self.api_post(u'/rest/p/test/wiki/page2/', status=429, **data)
+            r = self.api_post('/rest/p/test/wiki/page2/', status=429, **data)
             p = Page.query.get(title='page2')
             assert_equal(p, None)
 
@@ -116,7 +117,7 @@ class TestWikiApi(TestRestApiBase):
 
     def test_json_encoding_directly(self):
         # used in @expose('json')
-        assert_equal(tg.jsonify.encode('<'), '"\u003C"')
+        assert_equal(tg.jsonify.encode('<'), '"\\u003C"')
         # make sure these are unchanged
         assert_equal(json.dumps('<'), '"<"')
 
diff --git a/ForgeWiki/forgewiki/tests/functional/test_root.py b/ForgeWiki/forgewiki/tests/functional/test_root.py
index 29be374..f2fd42c 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_root.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_root.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import StringIO
 import allura
@@ -52,9 +53,9 @@ class TestRootController(TestController):
         return self.find_form(resp, cond)
 
     def test_root_index(self):
-        page_url = h.urlquote(u'/wiki/tést/')
+        page_url = h.urlquote('/wiki/tést/')
         r = self.app.get(page_url).follow()
-        assert u'tést' in r
+        assert 'tést' in r
         assert 'Create Page' in r
         # No 'Create Page' button if user doesn't have 'create' perm
         r = self.app.get('/wiki/Home',
@@ -62,10 +63,10 @@ class TestRootController(TestController):
         assert 'Create Page' not in r, r
 
     def test_create_wiki_page(self):
-        url = u"/p/test/wiki/create_wiki_page/"
+        url = "/p/test/wiki/create_wiki_page/"
         r = self.app.get(url)
-        assert u'test' in r
-        assert u'Create page' in r.body
+        assert 'test' in r
+        assert 'Create page' in r.body
 
     def test_root_markdown_syntax(self):
         response = self.app.get('/wiki/markdown_syntax/')
@@ -80,13 +81,13 @@ class TestRootController(TestController):
         assert 'Browse Pages' in response
 
     def test_root_new_page(self):
-        response = self.app.get('/wiki/new_page?title=' + h.urlquote(u'tést'))
-        assert u'tést' in response
+        response = self.app.get('/wiki/new_page?title=' + h.urlquote('tést'))
+        assert 'tést' in response
 
     def test_root_new_search(self):
-        self.app.get(h.urlquote(u'/wiki/tést/'))
-        response = self.app.get('/wiki/search/?q=' + h.urlquote(u'tést'))
-        assert u'Search wiki: tést' in response
+        self.app.get(h.urlquote('/wiki/tést/'))
+        response = self.app.get('/wiki/search/?q=' + h.urlquote('tést'))
+        assert 'Search wiki: tést' in response
 
     def test_feed(self):
         for ext in ['', '.rss', '.atom']:
@@ -151,7 +152,7 @@ class TestRootController(TestController):
 
     def test_nonexistent_page_edit(self):
         resp = self.app.get('/wiki/tést/')
-        assert resp.location.endswith(h.urlquote(u'/wiki/tést/edit')), resp.location
+        assert resp.location.endswith(h.urlquote('/wiki/tést/edit')), resp.location
         resp = resp.follow()
         assert 'tést' in resp
 
@@ -405,7 +406,7 @@ class TestRootController(TestController):
                 'text': 'sometext',
                 'labels': '',
                 })
-        assert_equal(spam_checker.check.call_args[0][0], u'tést\nsometext')
+        assert_equal(spam_checker.check.call_args[0][0], 'tést\nsometext')
         assert 'tést' in response
 
     def test_page_get_markdown(self):
diff --git a/ForgeWiki/forgewiki/tests/test_app.py b/ForgeWiki/forgewiki/tests/test_app.py
index 5abf101..4bdba8e 100644
--- a/ForgeWiki/forgewiki/tests/test_app.py
+++ b/ForgeWiki/forgewiki/tests/test_app.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import datetime
 import tempfile
 import json
diff --git a/ForgeWiki/forgewiki/tests/test_converters.py b/ForgeWiki/forgewiki/tests/test_converters.py
index f30bf1d..5e2bdfa 100644
--- a/ForgeWiki/forgewiki/tests/test_converters.py
+++ b/ForgeWiki/forgewiki/tests/test_converters.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 3c6c7ef..e078743 100644
--- a/ForgeWiki/forgewiki/tests/test_models.py
+++ b/ForgeWiki/forgewiki/tests/test_models.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 9750f0d..21918a0 100644
--- a/ForgeWiki/forgewiki/tests/test_wiki_roles.py
+++ b/ForgeWiki/forgewiki/tests/test_wiki_roles.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from tg import tmpl_context as c, app_globals as g
 
 from nose.tools import assert_equal
diff --git a/ForgeWiki/forgewiki/version.py b/ForgeWiki/forgewiki/version.py
index 1b493f8..192acec 100644
--- a/ForgeWiki/forgewiki/version.py
+++ b/ForgeWiki/forgewiki/version.py
@@ -15,5 +15,6 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 __version_info__ = (0, 0)
 __version__ = '.'.join(map(str, __version_info__))
diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index 55704e4..d089974 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 #-*- python -*-
+from __future__ import unicode_literals
 import json
 import logging
 import os
@@ -113,7 +114,7 @@ class ForgeWikiApp(Application):
     default_mount_label = 'Wiki'
     default_mount_point = 'wiki'
     ordinal = 5
-    default_root_page_name = u'Home'
+    default_root_page_name = 'Home'
     icons = {
         24: 'images/wiki_24.png',
         32: 'images/wiki_32.png',
@@ -747,7 +748,7 @@ class PageController(BaseController, FeedController):
         else:
             self.page.labels = []
         self.page.commit(subscribe=subscribe)
-        g.spam_checker.check(title + u'\n' + text, artifact=self.page,
+        g.spam_checker.check(title + '\n' + text, artifact=self.page,
                              user=c.user, content_type='wiki')
         if activity_verb == 'created':
             notification_tasks.send_usermentions_notification.post(self.page.index_id(), text)
diff --git a/ForgeWiki/setup.py b/ForgeWiki/setup.py
index 76db941..52c332f 100644
--- a/ForgeWiki/setup.py
+++ b/ForgeWiki/setup.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 from setuptools import setup, find_packages
 
 from forgewiki.version import __version__
diff --git a/fuse/accessfs.py b/fuse/accessfs.py
index 56808f8..62808ea 100644
--- a/fuse/accessfs.py
+++ b/fuse/accessfs.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import json
 import urllib
diff --git a/scripts/ApacheAccessHandler.py b/scripts/ApacheAccessHandler.py
index 70055d1..c9e8900 100644
--- a/scripts/ApacheAccessHandler.py
+++ b/scripts/ApacheAccessHandler.py
@@ -29,6 +29,7 @@ this authorization code without Allura set up and configured on the git host.
 """
 
 
+from __future__ import unicode_literals
 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 aa2fe1e..96835b5 100644
--- a/scripts/add_user_to_group.py
+++ b/scripts/add_user_to_group.py
@@ -36,6 +36,7 @@ Example:
 
 """
 
+from __future__ import unicode_literals
 from allura import model as M
 from ming.orm import ThreadLocalORMSession
 
diff --git a/scripts/changelog.py b/scripts/changelog.py
index 61aafdd..13300fd 100755
--- a/scripts/changelog.py
+++ b/scripts/changelog.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import sys
 import re
 import git
diff --git a/scripts/create-allura-sitemap.py b/scripts/create-allura-sitemap.py
index 7f76f6b..7e5b31b 100644
--- a/scripts/create-allura-sitemap.py
+++ b/scripts/create-allura-sitemap.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 0568fa0..a6dcea0 100644
--- a/scripts/migrations/013-update-ordinals.py
+++ b/scripts/migrations/013-update-ordinals.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 1fa8542..02bfb91 100644
--- a/scripts/migrations/015-add-neighborhood_id-to-blog-posts.py
+++ b/scripts/migrations/015-add-neighborhood_id-to-blog-posts.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 2a5469c..372c6fb 100644
--- a/scripts/migrations/018-add-svn-checkout-url.py
+++ b/scripts/migrations/018-add-svn-checkout-url.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 0df73f7..00c314a 100644
--- a/scripts/migrations/020-remove-wiki-title-slashes.py
+++ b/scripts/migrations/020-remove-wiki-title-slashes.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 dbe9911..8722d8e 100644
--- a/scripts/migrations/022-change-anon-display-name.py
+++ b/scripts/migrations/022-change-anon-display-name.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 060b70e..bf851b5 100644
--- a/scripts/migrations/024-migrate-custom-profile-text.py
+++ b/scripts/migrations/024-migrate-custom-profile-text.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 ca3fc77..e2e7fdf 100644
--- a/scripts/migrations/025-add-is-nbhd-project.py
+++ b/scripts/migrations/025-add-is-nbhd-project.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 c7eb39f..620a614 100644
--- a/scripts/migrations/026-install-activity-tool.py
+++ b/scripts/migrations/026-install-activity-tool.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 3c6877a..4f51e20 100644
--- a/scripts/migrations/027-change-ticket-write-permissions.py
+++ b/scripts/migrations/027-change-ticket-write-permissions.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 79e82aa..4023106 100644
--- a/scripts/migrations/028-remove-svn-trees.py
+++ b/scripts/migrations/028-remove-svn-trees.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 c2075b7..0f936fe 100644
--- a/scripts/migrations/029-set-mailbox-queue_empty.py
+++ b/scripts/migrations/029-set-mailbox-queue_empty.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 02d35d9..d243e8b 100644
--- a/scripts/migrations/031-set-user-pending-to-false.py
+++ b/scripts/migrations/031-set-user-pending-to-false.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 3791dd7..57aa778 100644
--- a/scripts/migrations/032-subscribe-merge-request-submitters.py
+++ b/scripts/migrations/032-subscribe-merge-request-submitters.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 f0b7da8..2dad964 100644
--- a/scripts/migrations/033-change-comment-anon-permissions.py
+++ b/scripts/migrations/033-change-comment-anon-permissions.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 94904c8..44093de 100644
--- a/scripts/migrations/034-update_subscriptions_ticket_and_mr_titles.py
+++ b/scripts/migrations/034-update_subscriptions_ticket_and_mr_titles.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import re
 import sys
diff --git a/scripts/new_ticket.py b/scripts/new_ticket.py
index 924f9d2..86c6ca8 100755
--- a/scripts/new_ticket.py
+++ b/scripts/new_ticket.py
@@ -16,6 +16,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import sys
 import argparse
 import requests
diff --git a/scripts/perf/benchmark-scm.py b/scripts/perf/benchmark-scm.py
index be9b93a..3dc70b4 100755
--- a/scripts/perf/benchmark-scm.py
+++ b/scripts/perf/benchmark-scm.py
@@ -18,6 +18,7 @@
 #       under the License.
 
 
+from __future__ import unicode_literals
 import os
 import sys
 import argparse
diff --git a/scripts/perf/call_count.py b/scripts/perf/call_count.py
index e94c238..669e95e 100755
--- a/scripts/perf/call_count.py
+++ b/scripts/perf/call_count.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import argparse
 import json
 import logging
diff --git a/scripts/perf/generate-projects.py b/scripts/perf/generate-projects.py
index 0374969..74d83ad 100644
--- a/scripts/perf/generate-projects.py
+++ b/scripts/perf/generate-projects.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 ee8f93d..38d134d 100644
--- a/scripts/perf/load-up-forum.py
+++ b/scripts/perf/load-up-forum.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 
+from __future__ import unicode_literals
 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 d4511da..baee3f5 100644
--- a/scripts/perf/md_perf.py
+++ b/scripts/perf/md_perf.py
@@ -45,6 +45,7 @@ sys     0m1.112s
 
 """
 
+from __future__ import unicode_literals
 import argparse
 import cProfile
 import time
diff --git a/scripts/perf/parse_timings.py b/scripts/perf/parse_timings.py
index f16052c..9bda703 100644
--- a/scripts/perf/parse_timings.py
+++ b/scripts/perf/parse_timings.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import json
 from datetime import datetime
 import argparse
diff --git a/scripts/perf/sstress.py b/scripts/perf/sstress.py
index 3f1a1b1..475a975 100644
--- a/scripts/perf/sstress.py
+++ b/scripts/perf/sstress.py
@@ -21,6 +21,7 @@
 sstress - an SMTP stress testing tool
 '''
 
+from __future__ import unicode_literals
 import smtplib
 import threading
 import time
diff --git a/scripts/perf/test_git_lcd.py b/scripts/perf/test_git_lcd.py
index 8d75e54..c992aa8 100644
--- a/scripts/perf/test_git_lcd.py
+++ b/scripts/perf/test_git_lcd.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import sys
 import os
 from glob import glob
diff --git a/scripts/project-import.py b/scripts/project-import.py
index 9833bc2..eedbf1d 100644
--- a/scripts/project-import.py
+++ b/scripts/project-import.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import bson
 import datetime
 import json
diff --git a/scripts/publicize-neighborhood.py b/scripts/publicize-neighborhood.py
index b2d208c..804d0e4 100644
--- a/scripts/publicize-neighborhood.py
+++ b/scripts/publicize-neighborhood.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import sys
 
diff --git a/scripts/rethumb.py b/scripts/rethumb.py
index 4dbfc04..8d84e5d 100644
--- a/scripts/rethumb.py
+++ b/scripts/rethumb.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import sys
 
 import PIL
diff --git a/scripts/scrub-allura-data.py b/scripts/scrub-allura-data.py
index 226ea13..8902426 100644
--- a/scripts/scrub-allura-data.py
+++ b/scripts/scrub-allura-data.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 import sys
 
diff --git a/scripts/teamforge-import.py b/scripts/teamforge-import.py
index 9bd88a6..ed920ad 100644
--- a/scripts/teamforge-import.py
+++ b/scripts/teamforge-import.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import logging
 from getpass import getpass
 from optparse import OptionParser
diff --git a/scripts/trac_export.py b/scripts/trac_export.py
index ac90b17..6fe9655 100755
--- a/scripts/trac_export.py
+++ b/scripts/trac_export.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 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 025d3ca..ef62ddf 100755
--- a/scripts/trac_export_wiki.py
+++ b/scripts/trac_export_wiki.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import sys
 from optparse import OptionParser
 
diff --git a/scripts/trac_import.py b/scripts/trac_import.py
index d4e51fd..55938ac 100644
--- a/scripts/trac_import.py
+++ b/scripts/trac_import.py
@@ -15,6 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import json
 from optparse import OptionParser
 
diff --git a/scripts/wiki-copy.py b/scripts/wiki-copy.py
index 26304cb..bfceec3 100644
--- a/scripts/wiki-copy.py
+++ b/scripts/wiki-copy.py
@@ -17,6 +17,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+from __future__ import unicode_literals
 import os
 import sys
 import urllib