浏览代码

HUE-8737 [py3] Fix useradmin and libs unit tests and fix urllib import in mako
liboozie.tests.test_config_gen
liboozie.tests.test_config_gen_negative
librdbms.tests.TestDatabasePasswordConfig.test_read_password_from_script
libsaml.tests.test_xmlsec_dynamic_default_no_which
useradmin.tests

Ying Chen 6 年之前
父节点
当前提交
0d6bbec088

+ 7 - 2
apps/filebrowser/src/filebrowser/templates/display.mako

@@ -16,15 +16,20 @@
 ## limitations under the License.
 <%!
   import datetime
-  import urllib
+  import sys
   from django.template.defaultfilters import urlencode, stringformat, date, filesizeformat, time
   from filebrowser.views import truncate
   from desktop.lib.paths import SAFE_CHARACTERS_URI_COMPONENTS
   from desktop.views import commonheader, commonfooter
   from django.utils.translation import ugettext as _
+
+  if sys.version_info[0] > 2:
+    from urllib.parse import quote as urllib_quote
+  else:
+    from urllib import quote as urllib_quote
 %>
 <%
-  path_enc = urllib.quote(path.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS)
+  path_enc = urllib_quote(path.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS)
   dirname_enc = urlencode(view['dirname'])
   base_url = url('filebrowser.views.view', path=path_enc)
   edit_url = url('filebrowser_views_edit', path=path_enc)

+ 9 - 4
apps/filebrowser/src/filebrowser/templates/fb_components.mako

@@ -15,13 +15,18 @@
 ## limitations under the License.
 <%!
 import datetime
-import urllib
+import sys
 from desktop.lib.paths import SAFE_CHARACTERS_URI_COMPONENTS
 
 from django.template.defaultfilters import urlencode, stringformat, date, filesizeformat, time
 from django.utils.translation import ugettext as _
 
 from aws.conf import get_default_region
+
+if sys.version_info[0] > 2:
+  from urllib.parse import quote as urllib_quote
+else:
+  from urllib import quote as urllib_quote
 %>
 
 <%def name="breadcrumbs(path, breadcrumbs, from_listdir=False)">
@@ -46,7 +51,7 @@ from aws.conf import get_default_region
             </span>
           </li>
         %else:
-          <li><a class="pointer breadcrumb-link homeLink" data-bind="click: $root.openHome, attr:{'href': window.HUE_BASE_URL + '/filebrowser/view=${ urllib.quote(path.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS) }?default_to_home'}">
+          <li><a class="pointer breadcrumb-link homeLink" data-bind="click: $root.openHome, attr:{'href': window.HUE_BASE_URL + '/filebrowser/view=${ urllib_quote(path.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS) }?default_to_home'}">
             <i class="fa fa-home"></i> ${_('Home')}</a>
           </li>
         %endif
@@ -63,7 +68,7 @@ from aws.conf import get_default_region
         </li>
         % if is_trash_enabled:
         <li class="pull-right">
-          <a class="pointer breadcrumb-link trashLink" data-bind="click: $root.openTrash, attr:{'href': window.HUE_BASE_URL + '/filebrowser/view=${ urllib.quote(path.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS) }?default_to_trash'}" title="${_('View trash')}">
+          <a class="pointer breadcrumb-link trashLink" data-bind="click: $root.openTrash, attr:{'href': window.HUE_BASE_URL + '/filebrowser/view=${ urllib_quote(path.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS) }?default_to_trash'}" title="${_('View trash')}">
             <i class="fa fa-trash-o"></i> ${_('Trash')}
           </a>
         </li>
@@ -71,7 +76,7 @@ from aws.conf import get_default_region
       </ul>
     % else:
       <ul class="nav nav-pills hue-breadcrumbs-bar">
-        <li><a data-bind="hueLink: window.HUE_BASE_URL + '/filebrowser/view=${ urllib.quote(path.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS) }?default_to_home'" class="breadcrumb-link homeLink"><i class="fa fa-home"></i> ${_('Home')}</a></li>
+        <li><a data-bind="hueLink: window.HUE_BASE_URL + '/filebrowser/view=${ urllib_quote(path.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS) }?default_to_home'" class="breadcrumb-link homeLink"><i class="fa fa-home"></i> ${_('Home')}</a></li>
         <li>
           <ul class="hue-breadcrumbs" style="padding-right:40px; padding-top: 12px">
           % for breadcrumb_item in breadcrumbs:

+ 0 - 1
apps/jobsub/src/jobsub/templates/designs.mako

@@ -15,7 +15,6 @@
 
 <%!
 import cgi
-import urllib
 import time
 from desktop.views import commonheader, commonfooter
 from django.utils.translation import ugettext as _

+ 7 - 2
apps/oozie/src/oozie/templates/dashboard/list_oozie_bundle.mako

@@ -16,12 +16,17 @@
 ## limitations under the License.
 
 <%!
-  import urllib
+  import sys
   from desktop.lib.paths import SAFE_CHARACTERS_URI_COMPONENTS
   from desktop.views import commonheader, commonfooter
   from django.utils.translation import ugettext as _
 
   from oozie.conf import ENABLE_V2
+
+  if sys.version_info[0] > 2:
+    from urllib.parse import quote as urllib_quote
+  else:
+    from urllib import quote as urllib_quote
 %>
 
 <%namespace name="layout" file="../navigation-bar.mako" />
@@ -110,7 +115,7 @@ ${ layout.menubar(section='bundles', dashboard=True) }
                % endif
             "
               id="rerun-btn"
-              data-rerun-url="${ url('oozie:rerun_oozie_bundle', job_id=oozie_bundle.id, app_path=urllib.quote(oozie_bundle.bundleJobPath.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS)) }"
+              data-rerun-url="${ url('oozie:rerun_oozie_bundle', job_id=oozie_bundle.id, app_path=urllib_quote(oozie_bundle.bundleJobPath.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS)) }"
             style="margin-bottom: 5px">
               ${ _('Rerun') }
             </button>

+ 7 - 2
apps/oozie/src/oozie/templates/dashboard/list_oozie_coordinator.mako

@@ -16,12 +16,17 @@
 ## limitations under the License.
 
 <%!
-  import urllib
+  import sys
   from desktop.lib.paths import SAFE_CHARACTERS_URI_COMPONENTS
   from desktop.views import commonheader, commonfooter, _ko
   from django.utils.translation import ugettext as _
   
   from oozie.conf import ENABLE_V2
+
+  if sys.version_info[0] > 2:
+    from urllib.parse import quote as urllib_quote
+  else:
+    from urllib import quote as urllib_quote
 %>
 
 <%namespace name="layout" file="../navigation-bar.mako" />
@@ -199,7 +204,7 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
                          % if oozie_coordinator.is_running() or oozie_coordinator.status in ('KILLED', 'FAILED'):
                            disabled="disabled"
                          % endif
-                        data-rerun-url="${ url('oozie:rerun_oozie_coord', job_id=oozie_coordinator.id, app_path=urllib.quote(oozie_coordinator.coordJobPath.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS)) }">
+                        data-rerun-url="${ url('oozie:rerun_oozie_coord', job_id=oozie_coordinator.id, app_path=urllib_quote(oozie_coordinator.coordJobPath.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS)) }">
                         <i class="fa fa-refresh"></i> ${ _('Rerun') }
                       </button>
                       <button id="trash-btn-caret" class="btn toolbarBtn dropdown-toggle" data-toggle="dropdown"

+ 0 - 1
apps/useradmin/src/useradmin/templates/add_ldap_users.mako

@@ -16,7 +16,6 @@
 <%!
 from desktop.views import commonheader, commonfooter
 from desktop.lib.django_util import extract_field_data
-import urllib
 from django.utils.translation import ugettext as _
 %>
 

+ 8 - 2
apps/useradmin/src/useradmin/templates/edit_group.mako

@@ -14,12 +14,18 @@
 ## See the License for the specific language governing permissions and
 ## limitations under the License.
 <%!
-import urllib
+import sys
 
 from django.utils.translation import ugettext as _
 
 from desktop.lib.django_util import extract_field_data
 from desktop.views import commonheader, commonfooter
+
+if sys.version_info[0] > 2:
+  from urllib.parse import quote as urllib_quote
+  unicode = str
+else:
+  from urllib import quote as urllib_quote
 %>
 
 <%namespace name="layout" file="layout.mako" />
@@ -58,7 +64,7 @@ ${ layout.menubar(section='groups') }
 
     <br/>
 
-    <form id="editForm" action="${urllib.quote(action)}" method="POST" class="form form-horizontal" autocomplete="off">
+    <form id="editForm" action="${urllib_quote(action)}" method="POST" class="form form-horizontal" autocomplete="off">
       ${ csrf_token(request) | n,unicode }
       <fieldset>
         % for field in form:

+ 8 - 2
apps/useradmin/src/useradmin/templates/edit_permissions.mako

@@ -14,10 +14,16 @@
 ## See the License for the specific language governing permissions and
 ## limitations under the License.
 <%!
-import urllib
+import sys
 
 from desktop.views import commonheader, commonfooter
 from django.utils.translation import ugettext as _
+
+if sys.version_info[0] > 2:
+  from urllib.parse import quote as urllib_quote
+  unicode = str
+else:
+  from urllib import quote as urllib_quote
 %>
 
 <%namespace name="layout" file="layout.mako" />
@@ -48,7 +54,7 @@ ${layout.menubar(section='permissions')}
     <h1 class="card-heading simple">${_('Hue Permissions - Edit app: %(app)s') % dict(app=app)}</h1>
     <br/>
 
-    <form id="editForm" action="${urllib.quote(action)}" method="POST" class="form form-horizontal">
+    <form id="editForm" action="${urllib_quote(action)}" method="POST" class="form form-horizontal">
       ${ csrf_token(request) | n,unicode }
       <fieldset>
           % for field in form:

+ 41 - 38
apps/useradmin/src/useradmin/tests.py

@@ -18,7 +18,6 @@
 
 from future import standard_library
 standard_library.install_aliases()
-from builtins import str
 from builtins import object
 import json
 import ldap
@@ -32,7 +31,6 @@ from nose.tools import assert_true, assert_equal, assert_false, assert_not_equal
 from datetime import datetime
 from django.contrib.sessions.models import Session
 from django.db.models import Q
-from django.utils.encoding import smart_unicode
 from django.urls import reverse
 from django.test.client import Client
 
@@ -54,6 +52,11 @@ from useradmin.middleware import ConcurrentUserSessionMiddleware
 from useradmin.models import HuePermission, GroupPermission, UserProfile, get_profile, get_default_user_group, User, Group
 from useradmin.hue_password_policy import reset_password_policy
 
+if sys.version_info[0] > 2:
+  from django.utils.encoding import smart_text as smart_unicode
+else:
+  from django.utils.encoding import smart_unicode
+
 
 def reset_all_users():
   """Reset to a clean state by deleting all users"""
@@ -270,7 +273,7 @@ class TestUserAdmin(BaseUserAdminTests):
 
     # Make sure that a superuser can always access applications
     response = c.get('/useradmin/users')
-    assert_true('Hue Users' in response.content)
+    assert_true(b'Hue Users' in response.content)
 
     assert_true(len(GroupPermission.objects.all()) == 0)
     c.post('/useradmin/groups/edit/test-group',
@@ -306,11 +309,11 @@ class TestUserAdmin(BaseUserAdminTests):
     # Create user to try to edit
     notused = User.objects.get_or_create(username="notused", is_superuser=False)
     response = cadmin.get('/useradmin/users/edit/notused?is_embeddable=true')
-    assert_true('Hue Users - Edit user: notused' in response.content)
+    assert_true(b'Hue Users - Edit user: notused' in response.content)
 
     # Make sure we can modify permissions
     response = cadmin.get('/useradmin/permissions/edit/useradmin/access/?is_embeddable=true')
-    assert_true('Hue Permissions - Edit app: useradmin' in response.content)
+    assert_true(b'Hue Permissions - Edit app: useradmin' in response.content)
 
     # Revoke superuser privilege from groups
     c.post('/useradmin/permissions/edit/useradmin/superuser', dict(
@@ -326,7 +329,7 @@ class TestUserAdmin(BaseUserAdminTests):
     # Now test that we have limited access
     c1 = make_logged_in_client(username="nonadmin", is_superuser=False)
     response = c1.get('/useradmin/users')
-    assert_true('You do not have permission to access the Useradmin application.' in response.content)
+    assert_true(b'You do not have permission to access the Useradmin application.' in response.content)
 
     # Add the non-admin to a group that should grant permissions to the app
     test_user = User.objects.get(username="nonadmin")
@@ -335,19 +338,19 @@ class TestUserAdmin(BaseUserAdminTests):
 
     # Make sure that a user of nonadmin fails where supertest succeeds
     response = c1.get("/useradmin/users/edit/notused?is_embeddable=true")
-    assert_true('You must be a superuser to add or edit another user' in response.content)
+    assert_true(b'You must be a superuser to add or edit another user' in response.content)
 
     response = c1.get("/useradmin/permissions/edit/useradmin/access/?is_embeddable=true")
-    assert_true('You must be a superuser to change permissions' in response.content)
+    assert_true(b'You must be a superuser to change permissions' in response.content)
 
     # Check that we have access now
     response = c1.get('/useradmin/users')
     assert_true(get_profile(test_user).has_hue_permission('access','useradmin'))
-    assert_true('Hue Users' in response.content)
+    assert_true(b'Hue Users' in response.content)
 
     # Make sure we can't modify permissions
     response = c1.get('/useradmin/permissions/edit/useradmin/access')
-    assert_true('must be a superuser to change permissions' in response.content)
+    assert_true(b'must be a superuser to change permissions' in response.content)
 
     # And revoke access from the group
     c.post('/useradmin/permissions/edit/useradmin/access', dict(
@@ -363,7 +366,7 @@ class TestUserAdmin(BaseUserAdminTests):
 
     # We should no longer have access to the app
     response = c1.get('/useradmin/users')
-    assert_true('You do not have permission to access the Useradmin application.' in response.content)
+    assert_true(b'You do not have permission to access the Useradmin application.' in response.content)
 
 
   def test_list_permissions(self):
@@ -408,7 +411,7 @@ class TestUserAdmin(BaseUserAdminTests):
       # Try deleting the default group
       assert_true(Group.objects.filter(name='test_default').exists())
       response = c.post('/useradmin/groups/delete', {'group_names': ['test_default']})
-      assert_true('default user group may not be deleted' in response.content)
+      assert_true(b'default user group may not be deleted' in response.content)
       assert_true(Group.objects.filter(name='test_default').exists())
 
       # Change the name of the default group, and try deleting again
@@ -435,7 +438,7 @@ class TestUserAdmin(BaseUserAdminTests):
     response = c.get('/useradmin/groups')
     # No groups just yet
     assert_true(len(response.context[0]["groups"]) == 0)
-    assert_true("Hue Groups" in response.content)
+    assert_true(b"Hue Groups" in response.content)
 
     # Create a group
     response = c.get('/useradmin/groups/new')
@@ -468,17 +471,17 @@ class TestUserAdmin(BaseUserAdminTests):
 
     # Make sure non-superusers can't do bad things
     response = c2.get('/useradmin/groups/new')
-    assert_true("You must be a superuser" in response.content)
+    assert_true(b"You must be a superuser" in response.content)
     response = c2.get('/useradmin/groups/edit/testgroup')
-    assert_true("You must be a superuser" in response.content)
+    assert_true(b"You must be a superuser" in response.content)
 
     response = c2.post('/useradmin/groups/new', dict(name="nonsuperuser"))
-    assert_true("You must be a superuser" in response.content)
+    assert_true(b"You must be a superuser" in response.content)
     response = c2.post('/useradmin/groups/edit/testgroup',
                       dict(name="nonsuperuser",
                       members=[User.objects.get(username="test").pk],
                       save="Save"), follow=True)
-    assert_true("You must be a superuser" in response.content)
+    assert_true(b"You must be a superuser" in response.content)
 
     # Should be one group left, because we created the other group
     response = c.post('/useradmin/groups/delete', {'group_names': ['testgroup']})
@@ -529,7 +532,7 @@ class TestUserAdmin(BaseUserAdminTests):
 
       # Test password hint is displayed
       response = c.get('/useradmin/users/edit/superuser')
-      assert_true(password_hint in response.content)
+      assert_true(password_hint in (response.content if isinstance(response.content, str) else response.content.decode()))
 
       # Password is less than 8 characters
       response = c.post('/useradmin/users/edit/superuser',
@@ -630,7 +633,7 @@ class TestUserAdmin(BaseUserAdminTests):
       # Test basic output.
       response = c.get('/useradmin/')
       assert_true(len(response.context[0]["users"]) > 0)
-      assert_true("Hue Users" in response.content)
+      assert_true(b"Hue Users" in response.content)
 
       # Test editing a superuser
       # Just check that this comes back
@@ -643,7 +646,7 @@ class TestUserAdmin(BaseUserAdminTests):
                              is_superuser=True,
                              is_active=True),
                         follow=True)
-      assert_true("User information updated" in response.content,
+      assert_true(b"User information updated" in response.content,
                   "Notification should be displayed in: %s" % response.content)
       # Edit it, can't change username
       response = c.post('/useradmin/users/edit/test',
@@ -653,20 +656,20 @@ class TestUserAdmin(BaseUserAdminTests):
                              is_superuser=True,
                              is_active=True),
                         follow=True)
-      assert_true("You cannot change a username" in response.content)
+      assert_true(b"You cannot change a username" in response.content)
       # Now make sure that those were materialized
       response = c.get('/useradmin/users/edit/test')
       assert_equal(smart_unicode("Inglés"), response.context[0]["form"].instance.first_name)
-      assert_true("Español" in response.content)
+      assert_true(("Español" if isinstance(response.content, str) else "Español".encode('utf-8')) in response.content)
       # Shouldn't be able to demote to non-superuser
       response = c.post('/useradmin/users/edit/test', dict(username="test",
                             first_name=u"Inglés", last_name=u"Español",
                             is_superuser=False, is_active=True))
-      assert_true("You cannot remove" in response.content,
+      assert_true(b"You cannot remove" in response.content,
                   "Shouldn't be able to remove the last superuser")
       # Shouldn't be able to delete oneself
       response = c.post('/useradmin/users/delete', {u'user_ids': [user.id]})
-      assert_true("You cannot remove yourself" in response.content,
+      assert_true(b"You cannot remove yourself" in response.content,
                   "Shouldn't be able to delete the last superuser")
 
       # Let's try changing the password
@@ -692,7 +695,7 @@ class TestUserAdmin(BaseUserAdminTests):
       group = get_default_user_group()
       response = c.get('/useradmin/users/new')
       assert_true(response)
-      assert_true(('<option value="%s" selected>%s</option>' % (group.id, group.name)) in str(response))
+      assert_true(('<option value="%s" selected>%s</option>' % (group.id, group.name)) in (response.content if isinstance(response.content, str) else response.content.decode()))
 
       # Create a new regular user (duplicate name)
       response = c.post('/useradmin/users/new', dict(username="test", password1="test", password2="test"))
@@ -713,9 +716,9 @@ class TestUserAdmin(BaseUserAdminTests):
       assert_equal(response.status_code, 200, response.content)
 
       response = c.get('/useradmin/')
-      assert_true(FUNNY_NAME in response.content, response.content)
+      assert_true(FUNNY_NAME in (response.content if isinstance(response.content, str) else response.content.decode()), response.content)
       assert_true(len(response.context[0]["users"]) > 1)
-      assert_true("Hue Users" in response.content)
+      assert_true(b"Hue Users" in response.content)
       # Validate profile is created.
       assert_true(UserProfile.objects.filter(user__username=FUNNY_NAME).exists())
 
@@ -750,7 +753,7 @@ class TestUserAdmin(BaseUserAdminTests):
       funny_user = User.objects.get(username=FUNNY_NAME)
       # Can't edit other people.
       response = c_reg.post("/useradmin/users/delete", {u'user_ids': [funny_user.id]})
-      assert_true("You must be a superuser" in response.content,
+      assert_true(b"You must be a superuser" in response.content,
                   "Regular user can't edit other people")
 
       # Revert to regular "test" user, that has superuser powers.
@@ -771,7 +774,7 @@ class TestUserAdmin(BaseUserAdminTests):
                                                      password2="test",
                                                      is_active=True))
       response = c.get('/useradmin/')
-      assert_true('christian_häusler' in response.content)
+      assert_true('christian_häusler' in (response.content if isinstance(response.content, str) else response.content.decode()))
       assert_true(len(response.context[0]["users"]) > 1)
 
       # Validate profile is created.
@@ -802,7 +805,7 @@ class TestUserAdmin(BaseUserAdminTests):
 
       # You shouldn't be able to create a user without a password
       response = c_su.post('/useradmin/users/new', dict(username="test"))
-      assert_true("You must specify a password when creating a new user." in response.content)
+      assert_true(b"You must specify a password when creating a new user." in response.content)
     finally:
       for reset in resets:
         reset()
@@ -876,18 +879,18 @@ class TestUserAdmin(BaseUserAdminTests):
     grant_access('test', 'test', 'useradmin')
 
     response = client.get('/useradmin/users/edit/test')
-    assert_true("Language Preference" in response.content)
+    assert_true(b"Language Preference" in response.content)
 
     # Does not appear for superuser editing other profiles
     other_client = make_logged_in_client('test_super', is_superuser=True, groupname='test')
     superuser = User.objects.get(username='test_super')
 
     response = other_client.get('/useradmin/users/edit/test')
-    assert_false("Language Preference" in response.content, response.content)
+    assert_false(b"Language Preference" in response.content, response.content)
 
     # Changing language preference will change language setting
     response = client.post('/useradmin/users/edit/test', dict(language='ko'))
-    assert_true('<option value="ko" selected>Korean</option>' in response.content)
+    assert_true(b'<option value="ko" selected>Korean</option>' in response.content)
 
   def test_edit_user_xss(self):
     # Hue 3 Admin
@@ -898,7 +901,7 @@ class TestUserAdmin(BaseUserAdminTests):
                                                                       password2="foo",
                                                                       language="en-us><script>alert('Hacked')</script>"
                                                                       ))
-    assert_true('Select a valid choice. en-us&gt;&lt;script&gt;alert(&#39;Hacked&#39;)&lt;/script&gt; is not one of the available choices.' in response.content)
+    assert_true(b'Select a valid choice. en-us&gt;&lt;script&gt;alert(&#39;Hacked&#39;)&lt;/script&gt; is not one of the available choices.' in response.content)
     # Hue 4 Admin
     response = edit_user.post('/useradmin/users/edit/admin', dict(username="admin",
                                                                       is_superuser=True,
@@ -916,7 +919,7 @@ class TestUserAdmin(BaseUserAdminTests):
                                                                       password2="foo",
                                                                       language="en-us><script>alert('Hacked')</script>"
                                                                       ))
-    assert_true('Select a valid choice. en-us&gt;&lt;script&gt;alert(&#39;Hacked&#39;)&lt;/script&gt; is not one of the available choices.' in response.content)
+    assert_true(b'Select a valid choice. en-us&gt;&lt;script&gt;alert(&#39;Hacked&#39;)&lt;/script&gt; is not one of the available choices.' in response.content)
     # Hue 4, User with access to useradmin app
     response = edit_user.post('/useradmin/users/edit/edit_user', dict(username="edit_user",
                                                                       is_superuser=False,
@@ -1050,20 +1053,20 @@ def test_get_connection_bind_password_script():
   # Unfortunately our tests leak a cached test ldap connection across functions, so we need to clear it out.
   useradmin.ldap_access.CACHED_LDAP_CONN = None
 
-  SCRIPT = '%s -c "print \'\\n password from script \\n\'"' % sys.executable
+  SCRIPT = '%s -c "print(\'\\n password from script \\n\')"' % sys.executable
 
   # Monkey patch the LdapConnection class as we don't want to make a real connection.
   OriginalLdapConnection = useradmin.ldap_access.LdapConnection
   reset = [
       desktop.conf.LDAP.LDAP_URL.set_for_testing('default.example.com'),
       desktop.conf.LDAP.BIND_PASSWORD_SCRIPT.set_for_testing(
-        '%s -c "print \'\\n default password \\n\'"' % sys.executable
+        '%s -c "print(\'\\n default password \\n\')"' % sys.executable
       ),
       desktop.conf.LDAP.LDAP_SERVERS.set_for_testing({
         'test': {
           'ldap_url': 'test.example.com',
           'bind_password_script':
-            '%s -c "print \'\\n test password \\n\'"' % sys.executable,
+            '%s -c "print(\'\\n test password \\n\')"' % sys.executable,
         }
       })
   ]

+ 2 - 0
desktop/core/src/desktop/lib/test_utils.py

@@ -83,6 +83,8 @@ def reformat_json(json_obj):
 
 def reformat_xml(xml_obj):
     if isinstance(xml_obj, basestring):
+        if not isinstance(xml_obj, bytes):
+            xml_obj = xml_obj.encode()
         return etree.tostring(objectify.fromstring(xml_obj, etree.XMLParser(strip_cdata=False, remove_blank_text=True)))
     else:
         return etree.tostring(xml_obj)

+ 1 - 1
desktop/core/src/desktop/tests.py

@@ -932,7 +932,7 @@ class TestStrictRedirection(object):
 
 class BaseTestPasswordConfig(object):
 
-  SCRIPT = '%s -c "print \'\\n password from script \\n\'"' % sys.executable
+  SCRIPT = '%s -c "print(\'\\n password from script \\n\')"' % sys.executable
 
   def get_config_password(self):
     raise NotImplementedError

+ 7 - 2
desktop/libs/dashboard/src/dashboard/templates/macros.mako

@@ -15,12 +15,17 @@
 ## limitations under the License.
 <%!
 import re
-import urllib
+import sys
 
 from itertools import izip
 
 from django.utils.translation import ugettext as _
 
+if sys.version_info[0] > 2:
+  from urllib.parse import quote as urllib_quote
+else:
+  from urllib import quote as urllib_quote
+
 
 # <http://github.com/mzsanford/twitter-text-java>
 
@@ -131,7 +136,7 @@ def shorten_url(text):
 
 def format_tag(tag, text):
     return '<a href="http://search.twitter.com/search?q=%s" target="_blank">%s%s</a>' \
-              % (urllib.quote('#' + text.encode('utf-8')), tag, text)
+              % (urllib_quote('#' + text.encode('utf-8')), tag, text)
 
 def format_username(at_char, user):
     return '<a href="http://twitter.com/%s" target="_blank">%s%s</a>' \

+ 2 - 2
desktop/libs/liboozie/src/liboozie/tests.py

@@ -64,7 +64,7 @@ def test_config_gen():
     'user.name': 'hue',
     'test.1': 'http://localhost/test?test1=test&test2=test'
   }
-  assert_equal(reformat_xml("""<configuration>
+  assert_equal(reformat_xml(b"""<configuration>
 <property>
   <name>test.1</name>
   <value><![CDATA[http://localhost/test?test1=test&test2=test]]></value>
@@ -80,7 +80,7 @@ def test_config_gen_negative():
     'user.name': 'hue<foo>bar</foo>',
     'test.1': 'http://localhost/test?test1=test&test2=test]]>&test3=test'
   }
-  assert_equal(reformat_xml("""<configuration>
+  assert_equal(reformat_xml(b"""<configuration>
 <property>
   <name>test.1</name>
   <value><![CDATA[http://localhost/test?test1=test&test2=test&test3=test]]></value>

+ 1 - 1
desktop/libs/liboozie/src/liboozie/utils.py

@@ -83,7 +83,7 @@ def config_gen(dic):
   print('<?xml version="1.0" encoding="UTF-8"?>', file=sio)
   print("<configuration>", file=sio)
   # if dic's key contains <,>,& then it will be escaped and if dic's value contains ']]>' then ']]>' will be stripped
-  for k, v in dic.items():
+  for k, v in sorted(dic.items()):
     print("<property>\n  <name>%s</name>\n  <value><![CDATA[%s]]></value>\n</property>\n" \
         % (escape(k), v.replace(']]>', '') if isinstance(v, basestring) else v), file=sio)
   print("</configuration>", file=sio)

+ 4 - 1
desktop/libs/libsaml/src/libsaml/conf.py

@@ -16,6 +16,7 @@
 # limitations under the License.
 
 import json
+import logging
 import os
 import subprocess
 
@@ -23,6 +24,7 @@ from django.utils.translation import ugettext_lazy as _t, ugettext as _
 
 from desktop.lib.conf import Config, coerce_bool, coerce_csv, coerce_password_from_script
 
+LOG = logging.getLogger(__name__)
 
 BASEDIR = os.path.dirname(os.path.abspath(__file__))
 
@@ -36,7 +38,8 @@ def xmlsec():
   try:
     proc = subprocess.Popen(['which', 'xmlsec1'], stdout=subprocess.PIPE)
     return proc.stdout.read().strip()
-  except (subprocess.CalledProcessError, OSError):
+  except Exception as e:
+    LOG.debug("xmlsec: %s" % e)
     return '/usr/local/bin/xmlsec1'