Эх сурвалжийг харах

HUE-8737 [core] Futurize apps/oozie for Python 3.5

Ying Chen 6 жил өмнө
parent
commit
e27c8ded30

+ 4 - 2
apps/oozie/examples/lib/pi.py

@@ -15,6 +15,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import print_function
+from builtins import range
 import pyspark
 import random
 
@@ -27,8 +29,8 @@ def sample(p):
     x,y = random.random(),random.random()
     return 1 if x*x + y*y < 1 else 0
 
-count = sc.parallelize(xrange(0, NUM_SAMPLES)) \
+count = sc.parallelize(range(0, NUM_SAMPLES)) \
             .map(sample) \
             .reduce(lambda a, b: a + b)
 
-print "Pi is roughly %f" % (4.0 * count / NUM_SAMPLES)
+print("Pi is roughly %f" % (4.0 * count / NUM_SAMPLES))

+ 2 - 1
apps/oozie/examples/managed/shell/hello.py

@@ -1,6 +1,7 @@
 #!/usr/bin/env python
 
+from __future__ import print_function
 import sys
 
-print 'Hello ' + ', '.join(sys.argv[1:])
+print('Hello ' + ', '.join(sys.argv[1:]))
 

+ 2 - 1
apps/oozie/examples/unmanaged/shell/hello.py

@@ -1,6 +1,7 @@
 #!/usr/bin/env python
 
+from __future__ import print_function
 import sys
 
-print 'Hello ' + ', '.join(sys.argv[1:])
+print('Hello ' + ', '.join(sys.argv[1:]))
 

+ 27 - 26
apps/oozie/src/oozie/forms.py

@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from builtins import object
 import logging
 from datetime import datetime,  timedelta
 from time import mktime, struct_time
@@ -64,12 +65,12 @@ class ParameterForm(forms.Form):
 
   @staticmethod
   def get_initial_params(conf_dict):
-    params = filter(lambda key: key not in ParameterForm.NON_PARAMETERS, conf_dict.keys())
+    params = [key for key in list(conf_dict.keys()) if key not in ParameterForm.NON_PARAMETERS]
     return [{'name': name, 'value': conf_dict[name]} for name in params]
 
 
 class WorkflowForm(forms.ModelForm):
-  class Meta:
+  class Meta(object):
     model = Workflow
     exclude = ('owner', 'start', 'end', 'data')
     widgets = {
@@ -100,20 +101,20 @@ class ImportJobsubDesignForm(forms.Form):
 
 
 class NodeForm(forms.ModelForm):
-  class Meta:
+  class Meta(object):
     ALWAYS_HIDE = ('workflow', 'children', 'node_type', 'data')
     model = Node
     exclude = ALWAYS_HIDE
 
 
 class NodeMetaForm(forms.ModelForm):
-  class Meta:
+  class Meta(object):
     ALWAYS_HIDE = ('workflow', 'children', 'node_type')
     model = Node
     exclude = ALWAYS_HIDE + ('name', 'description')
 
 class JavaForm(forms.ModelForm):
-  class Meta:
+  class Meta(object):
     model = Java
     exclude = NodeForm.Meta.ALWAYS_HIDE
     widgets = {
@@ -132,7 +133,7 @@ class JavaForm(forms.ModelForm):
 
 class MapreduceForm(forms.ModelForm):
   """Used for specifying a mapreduce action"""
-  class Meta:
+  class Meta(object):
     model = Mapreduce
     exclude = NodeForm.Meta.ALWAYS_HIDE
     widgets = {
@@ -148,7 +149,7 @@ class MapreduceForm(forms.ModelForm):
 
 class StreamingForm(forms.ModelForm):
   """Used for specifying a streaming action"""
-  class Meta:
+  class Meta(object):
     model = Streaming
     exclude = NodeForm.Meta.ALWAYS_HIDE
     widgets = {
@@ -163,7 +164,7 @@ class StreamingForm(forms.ModelForm):
 
 
 class PigForm(forms.ModelForm):
-  class Meta:
+  class Meta(object):
     model = Pig
     exclude = NodeForm.Meta.ALWAYS_HIDE
     widgets = {
@@ -179,7 +180,7 @@ class PigForm(forms.ModelForm):
 
 
 class HiveForm(forms.ModelForm):
-  class Meta:
+  class Meta(object):
     model = Hive
     exclude = NodeForm.Meta.ALWAYS_HIDE
     widgets = {
@@ -195,7 +196,7 @@ class HiveForm(forms.ModelForm):
 
 
 class SqoopForm(forms.ModelForm):
-  class Meta:
+  class Meta(object):
     model = Sqoop
     exclude = NodeForm.Meta.ALWAYS_HIDE
     widgets = {
@@ -211,7 +212,7 @@ class SqoopForm(forms.ModelForm):
 
 
 class SshForm(forms.ModelForm):
-  class Meta:
+  class Meta(object):
     model = Ssh
     exclude = NodeForm.Meta.ALWAYS_HIDE
     widgets = {
@@ -222,7 +223,7 @@ class SshForm(forms.ModelForm):
 
 
 class ShellForm(forms.ModelForm):
-  class Meta:
+  class Meta(object):
     model = Shell
     exclude = NodeForm.Meta.ALWAYS_HIDE
     widgets = {
@@ -238,7 +239,7 @@ class ShellForm(forms.ModelForm):
 
 
 class DistCpForm(forms.ModelForm):
-  class Meta:
+  class Meta(object):
     model = DistCp
     exclude = NodeForm.Meta.ALWAYS_HIDE
     widgets = {
@@ -252,7 +253,7 @@ class DistCpForm(forms.ModelForm):
 
 
 class FsForm(forms.ModelForm):
-  class Meta:
+  class Meta(object):
     model = Fs
     exclude = NodeForm.Meta.ALWAYS_HIDE
     widgets = {
@@ -265,7 +266,7 @@ class FsForm(forms.ModelForm):
 
 
 class EmailForm(forms.ModelForm):
-  class Meta:
+  class Meta(object):
     model = Email
     exclude = NodeForm.Meta.ALWAYS_HIDE
     widgets = {
@@ -284,7 +285,7 @@ class SubWorkflowForm(forms.ModelForm):
     choices=((wf.id, wf) for wf in Document.objects.available(Workflow, user) if workflow.id != id)
     self.fields['sub_workflow'] = forms.ChoiceField(choices=choices, required=False, widget=forms.RadioSelect(attrs={'class':'radio'}))
 
-  class Meta:
+  class Meta(object):
     model = SubWorkflow
     exclude = NodeForm.Meta.ALWAYS_HIDE
     widgets = {
@@ -300,7 +301,7 @@ class SubWorkflowForm(forms.ModelForm):
 
 
 class GenericForm(forms.ModelForm):
-  class Meta:
+  class Meta(object):
     model = Generic
     exclude = NodeForm.Meta.ALWAYS_HIDE
     widgets = {
@@ -311,13 +312,13 @@ class GenericForm(forms.ModelForm):
 class LinkForm(forms.ModelForm):
   comment = forms.CharField(label='if', max_length=1024, required=True, widget=forms.TextInput(attrs={'class': 'span8'}))
 
-  class Meta:
+  class Meta(object):
     model = Link
     exclude = NodeForm.Meta.ALWAYS_HIDE + ('parent', 'child', 'name')
 
 
 class DefaultLinkForm(forms.ModelForm):
-  class Meta:
+  class Meta(object):
     model = Link
     exclude = NodeForm.Meta.ALWAYS_HIDE + ('parent', 'comment', 'name')
 
@@ -344,7 +345,7 @@ class CoordinatorForm(forms.ModelForm):
                                  widget=SplitDateTimeWidget(attrs={'class': 'input-small', 'id': 'coordinator_end'},
                                                             date_format=DATE_FORMAT, time_format=TIME_FORMAT), localize=True)
 
-  class Meta:
+  class Meta(object):
     model = Coordinator
     exclude = ('owner', 'deployment_dir')
     if hasattr(ENABLE_CRON_SCHEDULING, 'get') and ENABLE_CRON_SCHEDULING.get():
@@ -391,7 +392,7 @@ class DatasetForm(forms.ModelForm):
                                    widget=SplitDateTimeWidget(attrs={'class': 'short'},
                                                               date_format=DATE_FORMAT, time_format=TIME_FORMAT))
 
-  class Meta:
+  class Meta(object):
     model = Dataset
     exclude = ('coordinator',)
     widgets = {
@@ -404,7 +405,7 @@ class DatasetForm(forms.ModelForm):
 
 
 class DataInputForm(forms.ModelForm):
-  class Meta:
+  class Meta(object):
     model = DataInput
     exclude = ('coordinator',)
 
@@ -418,7 +419,7 @@ class DataInputForm(forms.ModelForm):
 
 
 class DataOutputForm(forms.ModelForm):
-  class Meta:
+  class Meta(object):
     model = DataOutput
     exclude = ('coordinator',)
 
@@ -457,7 +458,7 @@ class RerunForm(forms.Form):
     return_json = kwargs.pop('return_json', None)
 
     # Build list of skip nodes
-    decisions = filter(lambda node: node.type == 'switch', oozie_workflow.get_control_flow_actions())
+    decisions = [node for node in oozie_workflow.get_control_flow_actions() if node.type == 'switch']
     working_actions = oozie_workflow.get_working_actions()
     skip_nodes = []
 
@@ -519,7 +520,7 @@ class BundledCoordinatorForm(forms.ModelForm):
     super(BundledCoordinatorForm, self).__init__(*args, **kwargs)
     self.fields['coordinator'].empty_label = None
 
-  class Meta:
+  class Meta(object):
     model = BundledCoordinator
     exclude = ('bundle',)
     widgets = {
@@ -532,7 +533,7 @@ class BundleForm(forms.ModelForm):
                                            widget=SplitDateTimeWidget(attrs={'class': 'input-small', 'id': 'bundle_kick_off_time'},
                                                                       date_format=DATE_FORMAT, time_format=TIME_FORMAT))
 
-  class Meta:
+  class Meta(object):
     model = Bundle
     exclude = ('owner', 'coordinators')
     widgets = {

+ 9 - 7
apps/oozie/src/oozie/importlib/workflows.py

@@ -31,6 +31,8 @@ Action extensions are also versioned.
 Every action extension will have its own version via /xslt/<workflow version>/extensions/<name of extensions>.<version>.xslt
 """
 
+from builtins import str
+from past.builtins import basestring
 import json
 import logging
 from lxml import etree
@@ -217,7 +219,7 @@ def _join_relationships(workflow, parent, child_el):
 
   try:
     child = Node.objects.get(workflow=workflow, name=to)
-  except Node.DoesNotExist, e:
+  except Node.DoesNotExist as e:
     raise RuntimeError(_("Node %s has not been defined.") % to)
 
   obj = Link.objects.create(name='to', parent=parent, child=child)
@@ -245,7 +247,7 @@ def _decision_relationships(workflow, parent, child_el):
       to = case.attrib['to']
       try:
         child = Node.objects.get(workflow=workflow, name=to)
-      except Node.DoesNotExist, e:
+      except Node.DoesNotExist as e:
         raise RuntimeError(_("Node %s has not been defined.") % to)
 
       if etree.QName(case).localname == 'default':
@@ -287,7 +289,7 @@ def _node_relationships(workflow, parent, child_el):
 
       try:
         child = Node.objects.get(workflow=workflow, name=to)
-      except Node.DoesNotExist, e:
+      except Node.DoesNotExist as e:
         if name == 'error':
           child, create = Kill.objects.get_or_create(name='kill', workflow=workflow, node_type=Kill.node_type)
         else:
@@ -509,7 +511,7 @@ def _prepare_nodes(workflow, root):
     else:
       node.node_type = obj.object.node_type
       full_node = obj.object
-      for k, v in vars(node).items():
+      for k, v in list(vars(node).items()):
         if not k.startswith('_') and k not in ('node_type','workflow','node_ptr_id'):
           setattr(full_node, k, v)
       full_node.workflow = workflow
@@ -583,11 +585,11 @@ def _resolve_subworkflow_from_deployment_dir(fs, workflow, app_path):
     return Workflow.objects.get(name=root.attrib['name'], owner=workflow.owner, managed=True)
   except IOError:
     pass
-  except (KeyError, AttributeError), e:
+  except (KeyError, AttributeError) as e:
     raise RuntimeError(_("Could not find workflow name when resolving subworkflow."))
-  except Workflow.DoesNotExist, e:
+  except Workflow.DoesNotExist as e:
     raise RuntimeError(_("Could not find workflow with name %s extracted from subworkflow path %s") % (root.attrib['name'], app_path))
-  except Exception, e:
+  except Exception as e:
     raise RuntimeError(_("Could not find workflow at path %s: %s") % (app_path, e))
 
   for subworkflow in Document.objects.available(Workflow, workflow.owner):

+ 4 - 4
apps/oozie/src/oozie/management/commands/oozie_setup.py

@@ -156,7 +156,7 @@ class Command(BaseCommand):
             description=data['description'],
             data=json.dumps(data)
           )
-      except Exception, e:
+      except Exception as e:
         LOG.exception("Failed to create sample mapreduce job document: %s" % e)
         # Just to be sure we delete Doc2 object incase of exception.
         # Possible when there are mixed InnoDB and MyISAM tables
@@ -208,7 +208,7 @@ class Command(BaseCommand):
             description=data['description'],
             data=json.dumps(data)
           )
-      except Exception, e:
+      except Exception as e:
         LOG.exception("Failed to create sample Java job document: %s" % e)
         # Just to be sure we delete Doc2 object incase of exception.
         # Possible when there are mixed InnoDB and MyISAM tables
@@ -261,7 +261,7 @@ class Command(BaseCommand):
             description=data['description'],
             data=json.dumps(data)
           )
-      except Exception, e:
+      except Exception as e:
         LOG.exception("Failed to create sample Spark job document: %s" % e)
         # Just to be sure we delete Doc2 object incase of exception.
         # Possible when there are mixed InnoDB and MyISAM tables
@@ -312,7 +312,7 @@ class Command(BaseCommand):
             description=data['description'],
             data=json.dumps(data)
           )
-      except Exception, e:
+      except Exception as e:
         LOG.exception("Failed to create sample PySpark job document: %s" % e)
         # Just to be sure we delete Doc2 object incase of exception.
         # Possible when there are mixed InnoDB and MyISAM tables

+ 27 - 17
apps/oozie/src/oozie/models.py

@@ -15,11 +15,16 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from future import standard_library
+standard_library.install_aliases()
+from builtins import range
+from past.builtins import basestring
+from builtins import object
 import json
 import copy
 import logging
 import re
-import StringIO
+import sys
 import time
 import zipfile
 
@@ -56,6 +61,11 @@ from oozie.timezones import TIMEZONES
 
 from desktop.auth.backend import is_admin
 
+if sys.version_info[0] > 2:
+  from io import StringIO as string_io
+else:
+  from cStringIO import StringIO as string_io
+
 
 LOG = logging.getLogger(__name__)
 
@@ -215,12 +225,12 @@ class Job(models.Model):
     for param in self.get_parameters():
       params[param['name'].strip()] = param['value']
 
-    return  [{'name': name, 'value': value} for name, value in params.iteritems()]
+    return  [{'name': name, 'value': value} for name, value in params.items()]
 
   def can_read(self, user):
     try:
       return self.doc.get().can_read(user)
-    except Exception, e:
+    except Exception as e:
       LOG.error('can_read failed because the object has more than one document: %s' % self.doc.all())
       raise e
 
@@ -306,9 +316,9 @@ class WorkflowManager(models.Manager):
     create_directories(fs)
 
     if workflow.is_shared:
-      perms = 0755
+      perms = 0o755
     else:
-      perms = 0711
+      perms = 0o711
 
     Submission(workflow.owner, workflow, fs, None, {})._create_dir(workflow.deployment_dir, perms=perms)
 
@@ -406,11 +416,11 @@ class Workflow(Job):
 
     try:
       if copy.is_shared:
-        perms = 0755
+        perms = 0o755
       else:
-        perms = 0711
+        perms = 0o711
       fs.copy_remote_dir(source_deployment_dir, copy.deployment_dir, owner=copy.owner, dir_mode=perms)
-    except WebHdfsException, e:
+    except WebHdfsException as e:
       msg = _('The copy of the deployment directory failed: %s.') % e
       LOG.error(msg)
       raise PopupException(msg)
@@ -561,7 +571,7 @@ class Workflow(Job):
         node_list = workflow.node_list
         workflow.delete(skip_trash=True)
         return graph, node_list
-    except Exception, e:
+    except Exception as e:
       LOG.warn('Workflow %s could not be converted to a graph: %s' % (oozie_workflow.id, e))
 
     return None, []
@@ -573,7 +583,7 @@ class Workflow(Job):
     xml = re.sub(re.compile('\s*\n+', re.MULTILINE), '\n', django_mako.render_to_string(tmpl, {'workflow': self, 'mapping': mapping}))
     return force_unicode(xml)
 
-  def compress(self, mapping=None, fp=StringIO.StringIO()):
+  def compress(self, mapping=None, fp=string_io()):
     metadata = {
       'version': Workflow.METADATA_FORMAT_VERSION,
       'nodes': {},
@@ -827,7 +837,7 @@ class Node(models.Model):
 class Action(Node):
   types = ()
 
-  class Meta:
+  class Meta(object):
     # Cloning does not work anymore if not abstract
     abstract = True
 
@@ -1242,7 +1252,7 @@ class ControlFlow(Node):
   """
   http://incubator.apache.org/oozie/docs/3.2.0-incubating/docs/WorkflowFunctionalSpec.html#a3.1_Control_Flow_Nodes
   """
-  class Meta:
+  class Meta(object):
     abstract = True
 
   def get_xml(self):
@@ -1386,7 +1396,7 @@ FREQUENCY_UNITS = (('minutes', _('Minutes')),
                    ('hours', _('Hours')),
                    ('days', _('Days')),
                    ('months', _('Months')))
-FREQUENCY_NUMBERS = [(i, i) for i in xrange(1, 61)]
+FREQUENCY_NUMBERS = [(i, i) for i in range(1, 61)]
 DATASET_FREQUENCY = ['MINUTE', 'HOUR', 'DAY', 'MONTH', 'YEAR']
 
 
@@ -1520,7 +1530,7 @@ class Coordinator(Job):
     datainput_names = [_input.name for _input in self.datainput_set.all()]
     dataoutput_names = [_output.name for _output in self.dataoutput_set.all()]
     removable_names = datainput_names + dataoutput_names
-    props = filter(lambda prop: prop['name'] not in removable_names, props)
+    props = [prop for prop in props if prop['name'] not in removable_names]
 
     return props
 
@@ -1573,7 +1583,7 @@ class Coordinator(Job):
 
     return params
 
-  def compress(self, mapping=None, fp=StringIO.StringIO()):
+  def compress(self, mapping=None, fp=string_io()):
     metadata = {
       'version': Coordinator.METADATA_FORMAT_VERSION,
       'workflow': self.workflow.name,
@@ -1847,7 +1857,7 @@ class Bundle(Job):
   def kick_off_time_utc(self):
     return utc_datetime_format(self.kick_off_time)
 
-  def compress(self, mapping=None, fp=StringIO.StringIO()):
+  def compress(self, mapping=None, fp=string_io()):
     metadata = {
       'version': Bundle.METADATA_FORMAT_VERSION,
       'attributes': {
@@ -1987,7 +1997,7 @@ def find_json_parameters(fields):
   params = []
 
   for field in fields:
-    for data in field.values():
+    for data in list(field.values()):
       if isinstance(data, basestring):
         for match in Template.pattern.finditer(data):
           name = match.group('braced')

+ 32 - 27
apps/oozie/src/oozie/models2.py

@@ -15,6 +15,11 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import division
+from builtins import str
+from past.builtins import basestring
+from past.utils import old_div
+from builtins import object
 import json
 import logging
 import os
@@ -67,7 +72,7 @@ class Job(object):
     if params.get('nominal_time') == '':
       params['nominal_time'] = datetime.today().strftime(UTC_TIME_FORMAT)
 
-    return  [{'name': name, 'value': value} for name, value in params.iteritems() if with_lib_path or name != 'oozie.use.system.libpath']
+    return  [{'name': name, 'value': value} for name, value in params.items() if with_lib_path or name != 'oozie.use.system.libpath']
 
   @classmethod
   def get_workspace(cls, user):
@@ -99,7 +104,7 @@ class Job(object):
   def import_workspace(self, fs, source_deployment_dir, owner):
     try:
       fs.copy_remote_dir(source_deployment_dir, self.deployment_dir, owner=owner)
-    except WebHdfsException, e:
+    except WebHdfsException as e:
       msg = _('The copy of the deployment directory failed: %s.') % e
       LOG.error(msg)
       raise PopupException(msg)
@@ -251,9 +256,9 @@ class Workflow(Job):
     node_list = []
     try:
       node_list = generate_v2_graph_nodes(oozie_workflow.definition)
-    except MalformedWfDefException, e:
+    except MalformedWfDefException as e:
       LOG.exception("Could not find any nodes in Workflow definition. Maybe it's malformed?")
-    except InvalidTagWithNamespaceException, e:
+    except InvalidTagWithNamespaceException as e:
       LOG.exception(
         "Tag with namespace %(namespace)s is not valid. Please use one of the following namespaces: %(namespaces)s" % {
           'namespace': e.namespace,
@@ -553,7 +558,7 @@ class Workflow(Job):
 # To avoid case-sensitive failures
 def _to_lowercase(node_list):
   for node in node_list:
-    for key in node.keys():
+    for key in list(node.keys()):
       if hasattr(node[key], 'lower'):
         node[key] = node[key].lower()
 
@@ -563,7 +568,7 @@ def _update_adj_list(adj_list):
   id = 1
   first_kill_node_seen = False
 
-  for node in adj_list.keys():
+  for node in list(adj_list.keys()):
     adj_list[node]['id'] = id
 
     # Oozie uses same action for streaming and mapreduce but Hue manages them differently
@@ -642,7 +647,7 @@ def _dig_nodes(nodes, adj_list, user, wf_nodes, nodes_uuid_set):
 
         children = []
         if node['node_type'] in ('fork', 'decision'):
-          for key in node.keys():
+          for key in list(node.keys()):
             if key.startswith('path'):
               children.append({'to': adj_list[node[key]]['uuid'], 'condition': '${ 1 gt 0 }'})
           if node['node_type'] == 'decision':
@@ -686,14 +691,14 @@ def _create_workflow_layout(nodes, adj_list, nodes_uuid_set, size=12):
           "columns":[
              {
                 "id": str(uuid.uuid4()),
-                "size": (size / len(node[1])),
+                "size": (old_div(size, len(node[1]))),
                 "rows":
                    [{
                       "id": str(uuid.uuid4()),
                       "widgets": c['widgets'],
                       "columns":c.get('columns') or []
                     } for c in col],
-                "klass":"card card-home card-column span%s" % (size / len(node[1]))
+                "klass":"card card-home card-column span%s" % (old_div(size, len(node[1])))
              }
              for col in [_create_workflow_layout(item, adj_list, nodes_uuid_set, size) for item in node[1]]
           ]
@@ -707,7 +712,7 @@ def _create_workflow_layout(nodes, adj_list, nodes_uuid_set, size=12):
 
 def _get_widget_type(node_type):
   widget_name = "%s-widget" % node_type
-  return widget_name if widget_name in NODES.keys() else 'generic-widget'
+  return widget_name if widget_name in list(NODES.keys()) else 'generic-widget'
 
 
 # Prevent duplicate nodes in graph layout
@@ -722,10 +727,10 @@ def _get_hierarchy_from_adj_list(adj_list, curr_node, node_hierarchy):
   _get_hierarchy_from_adj_list_helper(adj_list, curr_node, node_hierarchy, WORKFLOW_DEPTH_LIMIT)
 
   # Add End and Kill nodes to node_hierarchy
-  for key in adj_list.keys():
+  for key in list(adj_list.keys()):
     if adj_list[key]['node_type'] == 'kill':
       node_hierarchy.append([adj_list[key]['name']])
-  node_hierarchy.append([adj_list[key]['name'] for key in adj_list.keys() if adj_list[key]['node_type'] == 'end'])
+  node_hierarchy.append([adj_list[key]['name'] for key in list(adj_list.keys()) if adj_list[key]['node_type'] == 'end'])
 
 
 def _get_hierarchy_from_adj_list_helper(adj_list, curr_node, node_hierarchy, workflow_depth):
@@ -742,7 +747,7 @@ def _get_hierarchy_from_adj_list_helper(adj_list, curr_node, node_hierarchy, wor
 
     join_node = None
     children = []
-    for key in adj_list[curr_node].keys():
+    for key in list(adj_list[curr_node].keys()):
       if key.startswith('path') or key == 'default':
         child = []
         return_node = _get_hierarchy_from_adj_list_helper(adj_list, adj_list[curr_node][key], child, workflow_depth - 1)
@@ -774,7 +779,7 @@ def _create_graph_adjaceny_list(nodes):
   return adj_list
 
 
-class Node():
+class Node(object):
 
   def __init__(self, data, user=None):
     self.data = data
@@ -1084,7 +1089,7 @@ class Action(object):
   @classmethod
   def get_fields(cls):
     credentials = [cls.DEFAULT_CREDENTIALS] if hasattr(cls, 'DEFAULT_CREDENTIALS') and cls.DEFAULT_CREDENTIALS else []
-    return [(f['name'], f['value']) for f in cls.FIELDS.itervalues()] + [('sla', WorkflowConfiguration.SLA_DEFAULT), ('credentials', credentials)]
+    return [(f['name'], f['value']) for f in cls.FIELDS.values()] + [('sla', WorkflowConfiguration.SLA_DEFAULT), ('credentials', credentials)]
 
 
 class StartNode(Action):
@@ -1356,7 +1361,7 @@ def _get_hiveserver2_url():
   try:
     from beeswax.hive_site import hiveserver2_jdbc_url
     return hiveserver2_jdbc_url()
-  except Exception, e:
+  except Exception as e:
     # Might fail is Hive is disabled
     LOG.exception('Could not guess HiveServer2 URL: %s' % smart_str(e))
     return 'jdbc:hive2://localhost:10000/default'
@@ -1463,7 +1468,7 @@ def _get_impala_url():
   try:
     from impala.dbms import get_query_server_config
     return get_query_server_config()['server_host']
-  except Exception, e:
+  except Exception as e:
     # Might fail is Impala is disabled
     LOG.exception('Could not get Impalad URL: %s' % smart_str(e))
     return 'localhost'
@@ -2994,7 +2999,7 @@ NODES = {
 
 
 WORKFLOW_NODE_PROPERTIES = {}
-for node in NODES.itervalues():
+for node in NODES.values():
   WORKFLOW_NODE_PROPERTIES.update(node.FIELDS)
 
 
@@ -3002,7 +3007,7 @@ for node in NODES.itervalues():
 def find_parameters(instance, fields=None):
   """Find parameters in the given fields"""
   if fields is None:
-    fields = NODES['%s-widget' % instance.data['type']].FIELDS.keys()
+    fields = list(NODES['%s-widget' % instance.data['type']].FIELDS.keys())
 
   params = []
   for field in fields:
@@ -3024,7 +3029,7 @@ def find_json_parameters(fields):
   params = []
 
   for field in fields:
-    for data in field.values():
+    for data in list(field.values()):
       if isinstance(data, basestring):
         for match in Template.pattern.finditer(data):
           name = match.group('braced')
@@ -3117,7 +3122,7 @@ def import_workflow_from_hue_3_7(old_wf):
             "columns":[
                {
                   "id": str(uuid.uuid4()),
-                  "size": (size / len(node[1])),
+                  "size": (old_div(size, len(node[1]))),
                   "rows":
                      [{
                         "id": str(uuid.uuid4()),
@@ -3131,7 +3136,7 @@ def import_workflow_from_hue_3_7(old_wf):
                       }
                    ]
                   ,
-                  "klass":"card card-home card-column span%s" % (size / len(node[1]))
+                  "klass":"card card-home card-column span%s" % (old_div(size, len(node[1])))
                }
                for col in _create_layout(node[1], size)
             ]
@@ -3352,11 +3357,11 @@ class Coordinator(Job):
   def get_data_for_json(self):
     _data = self.data.copy()
 
-    start_date = filter(lambda a: a['name'] == 'start_date', self._data['properties']['parameters'])
+    start_date = [a for a in self._data['properties']['parameters'] if a['name'] == 'start_date']
     if start_date and type(start_date[0]['value']) == datetime:
       start_date[0]['value'] = start_date[0]['value'].strftime('%Y-%m-%dT%H:%M:%S')
 
-    end_date = filter(lambda a: a['name'] == 'end_date', self._data['properties']['parameters'])
+    end_date = [a for a in self._data['properties']['parameters'] if a['name'] == 'end_date']
     if end_date and type(end_date[0]['value']) == datetime:
       end_date[0]['value'] = end_date[0]['value'].strftime('%Y-%m-%dT%H:%M:%S')
 
@@ -3524,7 +3529,7 @@ class Coordinator(Job):
     return 'oozie.coord.application.path'
 
 
-class Dataset():
+class Dataset(object):
 
   def __init__(self, data, coordinator):
     self._data = data
@@ -3654,7 +3659,7 @@ class Bundle(Job):
 
   @property
   def data(self):
-    if type(self._data['properties']['kickoff']) == unicode:
+    if type(self._data['properties']['kickoff']) == str:
       self._data['properties']['kickoff'] = parse(self._data['properties']['kickoff'])
 
     if self.document is not None:
@@ -3794,7 +3799,7 @@ def _save_workflow(workflow, layout, user, fs=None):
   return workflow_doc
 
 
-class WorkflowBuilder():
+class WorkflowBuilder(object):
   """
   Building a workflow that has saved Documents for nodes (e.g Saved Hive query, saved Pig script...).
   """

+ 4 - 2
apps/oozie/src/oozie/models2_tests.py

@@ -16,6 +16,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from builtins import str
+from builtins import object
 import json
 import logging
 import re
@@ -354,7 +356,7 @@ LIMIT $limit"""))
     try:
       response = self.c.get(reverse('oozie:submit_single_action', args=[wf_doc.id, '3f107997-04cc-8733-60a9-a4bb62cebabc']))
       assert_equal([{'name':'Dryrun', 'value': False}, {'name':'ls_arg', 'value': '-l'}], response.context[0]._data['params_form'].initial)
-    except Exception, ex:
+    except Exception as ex:
       logging.exception(ex)
     finally:
       reset()
@@ -615,7 +617,7 @@ class TestExternalWorkflowGraph(object):
     adj_list = _create_graph_adjaceny_list(self.node_list)
 
     assert_true(len(adj_list) == 7)
-    assert_true('subworkflow-a13f' in adj_list.keys())
+    assert_true('subworkflow-a13f' in list(adj_list.keys()))
     assert_true(adj_list['shell-0f44']['shell']['command'] == 'ls')
     assert_equal(adj_list['fork-68d4'], {u'path2': u'shell-0f44', u'node_type': u'fork', u'ok_to': u'', u'name': u'fork-68d4', u'path1': u'subworkflow-a13f'})
 

+ 1 - 1
apps/oozie/src/oozie/old_migrations/0016_auto__add_field_coordinator_job_properties.py

@@ -14,7 +14,7 @@ class Migration(SchemaMigration):
         try:
           from oozie.models import Coordinator
           Coordinator.objects.all().update(job_properties='[]')
-        except Exception, e:
+        except Exception as e:
           import logging
           logging.warn(e)
 

+ 1 - 0
apps/oozie/src/oozie/old_migrations/0025_change_examples_path_format.py

@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from past.builtins import basestring
 import datetime
 import json
 from south.db import db

+ 18 - 8
apps/oozie/src/oozie/tests.py

@@ -16,11 +16,17 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from future import standard_library
+from functools import reduce
+standard_library.install_aliases()
+from builtins import str
+from past.builtins import basestring
+from builtins import object
 import json
 import logging
 import re
+import sys
 import os
-import StringIO
 import shutil
 import tempfile
 import zipfile
@@ -56,6 +62,10 @@ from oozie.utils import workflow_to_dict, model_to_dict, smart_path, contains_sy
 from oozie.importlib.workflows import import_workflow
 from oozie.importlib.jobdesigner import convert_jobsub_design
 
+if sys.version_info[0] > 2:
+  from io import StringIO as string_io
+else:
+  from cStringIO import StringIO as string_io
 
 LOG = logging.getLogger(__name__)
 
@@ -63,7 +73,7 @@ LOG = logging.getLogger(__name__)
 _INITIALIZED = False
 
 
-class MockOozieApi:
+class MockOozieApi(object):
   JSON_WORKFLOW_LIST = [{u'status': u'RUNNING', u'run': 0, u'startTime': u'Mon, 30 Jul 2012 22:35:48 GMT', u'appName': u'WordCount1', u'lastModTime': u'Mon, 30 Jul 2012 22:37:00 GMT', u'actions': [], u'acl': None, u'appPath': None, u'externalId': 'job_201208072118_0044', u'consoleUrl': u'http://runreal:11000/oozie?job=0000012-120725142744176-oozie-oozi-W', u'conf': None, u'parentId': None, u'createdTime': u'Mon, 30 Jul 2012 22:35:48 GMT', u'toString': u'Workflow id[0000012-120725142744176-oozie-oozi-W] status[SUCCEEDED]', u'endTime': u'Mon, 30 Jul 2012 22:37:00 GMT', u'id': u'0000012-120725142744176-oozie-oozi-W', u'group': None, u'user': u'test'},
                         {u'status': u'KILLED', u'run': 0, u'startTime': u'Mon, 30 Jul 2012 22:31:08 GMT', u'appName': u'WordCount2', u'lastModTime': u'Mon, 30 Jul 2012 22:32:20 GMT', u'actions': [], u'acl': None, u'appPath': None, u'externalId': '-', u'consoleUrl': u'http://runreal:11000/oozie?job=0000011-120725142744176-oozie-oozi-W', u'conf': None, u'parentId': None, u'createdTime': u'Mon, 30 Jul 2012 22:31:08 GMT', u'toString': u'Workflow id[0000011-120725142744176-oozie-oozi-W] status[SUCCEEDED]', u'endTime': u'Mon, 30 Jul 2012 22:32:20 GMT', u'id': u'0000011-120725142744176-oozie-oozi-W', u'group': None, u'user': u'test'},
                         {u'status': u'SUCCEEDED', u'run': 0, u'startTime': u'Mon, 30 Jul 2012 22:20:48 GMT', u'appName': u'WordCount3', u'lastModTime': u'Mon, 30 Jul 2012 22:22:00 GMT', u'actions': [], u'acl': None, u'appPath': None, u'externalId': '', u'consoleUrl': u'http://runreal:11000/oozie?job=0000009-120725142744176-oozie-oozi-W', u'conf': None, u'parentId': None, u'createdTime': u'Mon, 30 Jul 2012 22:20:48 GMT', u'toString': u'Workflow id[0000009-120725142744176-oozie-oozi-W] status[SUCCEEDED]', u'endTime': u'Mon, 30 Jul 2012 22:22:00 GMT', u'id': u'0000009-120725142744176-oozie-oozi-W', u'group': None, u'user': u'test'},
@@ -130,7 +140,7 @@ class MockOozieApi:
     workflows = MockOozieApi.JSON_WORKFLOW_LIST
     user_filters = [val for key, val in kwargs['filters'] if key == 'user']
     if user_filters:
-      workflows = filter(lambda wf: wf['user'] == user_filters[0], workflows)
+      workflows = [wf for wf in workflows if wf['user'] == user_filters[0]]
 
     return WorkflowList(self, {'offset': 0, 'total': 5, 'workflows': workflows})
 
@@ -138,7 +148,7 @@ class MockOozieApi:
     coordinatorjobs = MockOozieApi.JSON_COORDINATOR_LIST
     user_filters = [val for key, val in kwargs['filters'] if key == 'user']
     if user_filters:
-      coordinatorjobs = filter(lambda coord: coord['user'] == user_filters[0], coordinatorjobs)
+      coordinatorjobs = [coord for coord in coordinatorjobs if coord['user'] == user_filters[0]]
 
     return CoordinatorList(self, {'offset': 0, 'total': 5, 'coordinatorjobs': coordinatorjobs})
 
@@ -146,7 +156,7 @@ class MockOozieApi:
     bundlejobs = MockOozieApi.JSON_BUNDLE_LIST
     user_filters = [val for key, val in kwargs['filters'] if key == 'user']
     if user_filters:
-      bundlejobs = filter(lambda coord: coord['user'] == user_filters[0], bundlejobs)
+      bundlejobs = [coord for coord in bundlejobs if coord['user'] == user_filters[0]]
 
     return BundleList(self, {'offset': 0, 'total': 4, 'bundlejobs': bundlejobs})
 
@@ -237,7 +247,7 @@ class MockOozieApi:
     return {'status': "RUNNING"}
 
 
-class MockFs():
+class MockFs(object):
   def __init__(self, logical_name=None):
 
     self.fs_defaultfs = 'hdfs://curacao:8020'
@@ -1952,7 +1962,7 @@ class TestEditor(OozieMockBase):
 
   def test_workflow_export(self):
     response = self.c.get(reverse('oozie:export_workflow', args=[self.wf.id]))
-    zfile = zipfile.ZipFile(StringIO.StringIO(response.content))
+    zfile = zipfile.ZipFile(string_io(response.content))
     assert_true('workflow.xml' in zfile.namelist(), 'workflow.xml not in response')
     assert_true('workflow-metadata.json' in zfile.namelist(), 'workflow-metadata.json not in response')
     assert_equal(2, len(zfile.namelist()))
@@ -3269,7 +3279,7 @@ my_prop_not_filtered=10
         u'form-2-value': [u'/path/output'],
     }, follow=True)
 
-    assert_true('oozie_workflow' in response.context[0]._data.keys(), response.content)
+    assert_true('oozie_workflow' in list(response.context[0]._data.keys()), response.content)
     wf_id = response.context[0]._data['oozie_workflow'].id
 
     # Check if response contains log data

+ 10 - 6
apps/oozie/src/oozie/utils.py

@@ -15,10 +15,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from future import standard_library
+standard_library.install_aliases()
+from builtins import str
+from past.builtins import basestring
 import json
 import logging
 import re
-import urlparse
+import urllib.parse
 from datetime import datetime
 from dateutil import tz
 from dateutil import parser
@@ -74,7 +78,7 @@ def model_to_dict(model):
         dictionary[field.name] = str(attr)
       else:
         dictionary[field.name] = attr
-    except Exception, e:
+    except Exception as e:
       LOG.debug(_("Could not set field %(field)s: %(exception)s") % {'field': field.name, 'exception': str(e)})
   return dictionary
 
@@ -108,7 +112,7 @@ def smart_path(path, mapping=None, is_coordinator=False):
     mapping = {}
 
   path = path.strip()
-  if not path.startswith('$') and not path.startswith('/') and not urlparse.urlsplit(path).scheme:
+  if not path.startswith('$') and not path.startswith('/') and not urllib.parse.urlsplit(path).scheme:
     path = '/user/%(username)s/%(path)s' % {
         'username': '${coord:user()}' if is_coordinator else '${wf:user()}',
         'path': path
@@ -120,10 +124,10 @@ def smart_path(path, mapping=None, is_coordinator=False):
       prefix = '${%s}' % var
       if path.startswith(prefix):
         if var in mapping:
-          if not urlparse.urlsplit(mapping[var]).scheme and not mapping[var].startswith('$'):
+          if not urllib.parse.urlsplit(mapping[var]).scheme and not mapping[var].startswith('$'):
             path = '%(nameNode)s%(path)s' % {'nameNode': '${nameNode}', 'path': path}
   else:
-    if not urlparse.urlsplit(path).scheme:
+    if not urllib.parse.urlsplit(path).scheme:
       path = '%(nameNode)s%(path)s' % {'nameNode': '${nameNode}', 'path': path}
 
   return path
@@ -198,6 +202,6 @@ def convert_to_server_timezone(date, local_tz='UTC', server_tz=None, user=DEFAUL
       return date_server_tz.strftime('%Y-%m-%dT%H:%M') + u'Z'
     else:
       return date_server_tz.strftime('%Y-%m-%dT%H:%M') + date_server_tz.strftime('%z')
-  except TypeError, ValueError:
+  except TypeError as ValueError:
     LOG.error("Failed to convert Oozie timestamp: %s" % date)
   return None

+ 3 - 2
apps/oozie/src/oozie/views/__init__.py

@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from dashboard import *
-from editor import *
+from __future__ import absolute_import
+from .dashboard import *
+from .editor import *
 

+ 8 - 5
apps/oozie/src/oozie/views/api.py

@@ -15,6 +15,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from builtins import str
+from builtins import range
+from past.builtins import basestring
 import json
 import logging
 import re
@@ -50,13 +53,13 @@ def error_handler(view_fn):
   def decorator(request, *args, **kwargs):
     try:
       return view_fn(request, *args, **kwargs)
-    except Http404, e:
+    except Http404 as e:
       raise e
-    except StructuredException, e:
+    except StructuredException as e:
       error_code = e.error_code
       message = e.message
       details = e.data or {}
-    except Exception, e:
+    except Exception as e:
       LOG.exception('error in %s' % view_fn)
 
       error_code = 500
@@ -219,7 +222,7 @@ def _validate_nodes_json(json_nodes, errors, user, workflow):
       node_result = True
     link_result = _validate_node_links_json(node['node_type'], node_dict['child_links'], _errors)
     result = result and node_result and link_result
-    if not node.has_key('name') and ( not node.has_key('node_type') or not node.has_key('id') ):
+    if 'name' not in node and ( 'node_type' not in node or 'id' not in node ):
       raise StructuredException(code="INVALID_REQUEST_ERROR", message=_('Error saving workflow'), data={'errors': 'Node is missing a name.'}, error_code=400)
     errors[node.get('name', '%s-%s' % ( node.get('node_type'), node.get('id')))] = _errors
 
@@ -266,7 +269,7 @@ def _update_workflow_nodes_json(workflow, json_nodes, id_map, user):
     nodes.append(node)
 
   # Delete unused nodes from workflow
-  old_nodes = Node.objects.filter(workflow=workflow).exclude(id__in=map(lambda x: x.id, nodes))
+  old_nodes = Node.objects.filter(workflow=workflow).exclude(id__in=[x.id for x in nodes])
   for node in old_nodes:
     node.get_full_node().delete()
 

+ 25 - 22
apps/oozie/src/oozie/views/dashboard.py

@@ -15,12 +15,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from future import standard_library
+standard_library.install_aliases()
+from builtins import str
 import json
 import logging
 import os
 import re
 import time
-import urllib
+import urllib.request, urllib.parse, urllib.error
 
 from django.forms.formsets import formset_factory
 from django.http import HttpResponse
@@ -132,7 +135,7 @@ def manage_oozie_jobs(request, job_id, action):
     response['status'] = 0
     if 'notification' in request.POST:
       request.info(_(request.POST.get('notification')))
-  except RestException, ex:
+  except RestException as ex:
     ex_message = ex.message
     if ex._headers.get('oozie-error-message'):
       ex_message = ex._headers.get('oozie-error-message')
@@ -161,7 +164,7 @@ def bulk_manage_oozie_jobs(request):
       check_job_edition_permission(job, request.user)
       try:
         oozie_api.job_control(job_id, request.POST.get('action'))
-      except RestException, ex:
+      except RestException as ex:
         LOG.exception("Error performing bulk operation for job_id=%s", job_id)
 
         response['totalErrors'] = response['totalErrors'] + 1
@@ -174,7 +177,7 @@ def show_oozie_error(view_func):
   def decorate(request, *args, **kwargs):
     try:
       return view_func(request, *args, **kwargs)
-    except RestException, ex:
+    except RestException as ex:
       LOG.exception("Error communicating with Oozie in %s", view_func.__name__)
 
       detail = ex._headers.get('oozie-error-message', ex)
@@ -350,7 +353,7 @@ def list_oozie_workflow(request, job_id):
         new_workflow = get_workflow()(document=doc)
         workflow_data = new_workflow.get_data()
 
-    except Exception, e:
+    except Exception as e:
       LOG.exception("Error generating full page for running workflow %s with exception: %s" % (job_id, e.message))
     finally:
       workflow_graph = ''
@@ -361,7 +364,7 @@ def list_oozie_workflow(request, job_id):
           # Hide graph tab when node count > 30
           if workflow_data.get('workflow') and len(workflow_data.get('workflow')['nodes']) > 30:
             workflow_data = {}
-        except Exception, e:
+        except Exception as e:
           LOG.exception('Graph data could not be generated from Workflow %s: %s' % (oozie_workflow.id, e))
   else:
     history = get_history().cross_reference_submission_history(request.user, job_id)
@@ -409,7 +412,7 @@ def list_oozie_workflow(request, job_id):
       'workflow_graph': workflow_graph,
       'layout_json': json.dumps(workflow_data.get('layout', ''), cls=JSONEncoderForHTML) if workflow_data else '',
       'workflow_json': json.dumps(workflow_data.get('workflow', ''), cls=JSONEncoderForHTML) if workflow_data else '',
-      'credentials_json': json.dumps(credentials.credentials.keys(), cls=JSONEncoderForHTML) if credentials else '',
+      'credentials_json': json.dumps(list(credentials.credentials.keys()), cls=JSONEncoderForHTML) if credentials else '',
       'workflow_properties_json': json.dumps(WORKFLOW_NODE_PROPERTIES, cls=JSONEncoderForHTML),
       'doc_uuid': doc.uuid if doc else '',
       'graph_element_id': request.GET.get('element') if request.GET.get('element') else 'loaded ' + doc.uuid + ' graph',
@@ -435,12 +438,12 @@ def list_oozie_workflow(request, job_id):
     'oozie_slas': oozie_slas,
     'hue_workflow': hue_workflow,
     'hue_coord': hue_coord,
-    'parameters': dict((var, val) for var, val in parameters.iteritems() if var not in ParameterForm.NON_PARAMETERS and var != 'oozie.use.system.libpath' or var == 'oozie.wf.application.path'),
+    'parameters': dict((var, val) for var, val in parameters.items() if var not in ParameterForm.NON_PARAMETERS and var != 'oozie.use.system.libpath' or var == 'oozie.wf.application.path'),
     'has_job_edition_permission': has_job_edition_permission,
     'workflow_graph': workflow_graph,
     'layout_json': json.dumps(workflow_data.get('layout', ''), cls=JSONEncoderForHTML) if workflow_data else '',
     'workflow_json': json.dumps(workflow_data.get('workflow', ''), cls=JSONEncoderForHTML) if workflow_data else '',
-    'credentials_json': json.dumps(credentials.credentials.keys(), cls=JSONEncoderForHTML) if credentials else '',
+    'credentials_json': json.dumps(list(credentials.credentials.keys()), cls=JSONEncoderForHTML) if credentials else '',
     'workflow_properties_json': json.dumps(WORKFLOW_NODE_PROPERTIES, cls=JSONEncoderForHTML),
     'doc_uuid': doc.uuid if doc else '',
     'subworkflows_json': json.dumps(_get_workflows(request.user), cls=JSONEncoderForHTML),
@@ -551,7 +554,7 @@ def list_oozie_workflow_action(request, action):
   try:
     action = get_oozie(request.user).get_action(action)
     workflow = check_job_access_permission(request, action.id.split('@')[0])
-  except RestException, ex:
+  except RestException as ex:
     msg = _("Error accessing Oozie action %s.") % (action,)
     LOG.exception(msg)
 
@@ -741,7 +744,7 @@ def sync_coord_workflow(request, job_id):
 
     # Set previous values
     if properties:
-      new_params = dict([(key, properties[key]) if key in properties.keys() else (key, new_params[key]) for key, value in new_params.iteritems()])
+      new_params = dict([(key, properties[key]) if key in list(properties.keys()) else (key, new_params[key]) for key, value in new_params.items()])
 
     initial_params = ParameterForm.get_initial_params(new_params)
     params_form = ParametersFormSet(initial=initial_params)
@@ -762,7 +765,7 @@ def rerun_oozie_job(request, job_id, app_path=None):
   if app_path is None:
     app_path = oozie_workflow.appPath
   else:
-    app_path = urllib.unquote(app_path)
+    app_path = urllib.parse.unquote(app_path)
   return_json = request.GET.get('format') == 'json'
 
   if request.method == 'POST':
@@ -797,7 +800,7 @@ def rerun_oozie_job(request, job_id, app_path=None):
     return render('dashboard/rerun_workflow_popup.mako', request, {
                    'rerun_form': rerun_form,
                    'params_form': params_form,
-                   'action': reverse('oozie:rerun_oozie_job', kwargs={'job_id': job_id, 'app_path': urllib.quote(app_path.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS) }),
+                   'action': reverse('oozie:rerun_oozie_job', kwargs={'job_id': job_id, 'app_path': urllib.parse.quote(app_path.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS) }),
                    'return_json': return_json,
                    'is_mini': request.GET.get('is_mini', False),
                  }, force_template=True)
@@ -808,7 +811,7 @@ def _rerun_workflow(request, oozie_id, run_args, mapping):
     submission = Submission(user=request.user, fs=request.fs, jt=request.jt, properties=mapping, oozie_id=oozie_id)
     job_id = submission.rerun(**run_args)
     return job_id
-  except RestException, ex:
+  except RestException as ex:
     msg = _("Error re-running workflow %s.") % (oozie_id,)
     LOG.exception(msg)
 
@@ -823,7 +826,7 @@ def rerun_oozie_coordinator(request, job_id, app_path=None):
   if app_path is None:
     app_path = oozie_coordinator.coordJobPath
   else:
-    app_path = urllib.unquote(app_path)
+    app_path = urllib.parse.unquote(app_path)
   return_json = request.GET.get('format') == 'json'
 
   if request.method == 'POST':
@@ -861,7 +864,7 @@ def rerun_oozie_coordinator(request, job_id, app_path=None):
     return render('dashboard/rerun_coord_popup.mako', request, {
                    'rerun_form': rerun_form,
                    'params_form': params_form,
-                   'action': reverse('oozie:rerun_oozie_coord', kwargs={'job_id': job_id, 'app_path': urllib.quote(app_path.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS)}),
+                   'action': reverse('oozie:rerun_oozie_coord', kwargs={'job_id': job_id, 'app_path': urllib.parse.quote(app_path.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS)}),
                    'return_json': return_json,
                    'is_mini': request.GET.get('is_mini', False),
                  }, force_template=True)
@@ -872,7 +875,7 @@ def _rerun_coordinator(request, oozie_id, args, params, properties):
     submission = Submission(user=request.user, fs=request.fs, jt=request.jt, oozie_id=oozie_id, properties=properties)
     job_id = submission.rerun_coord(params=params, **args)
     return job_id
-  except RestException, ex:
+  except RestException as ex:
     msg = _("Error re-running coordinator %s.") % (oozie_id,)
     LOG.exception(msg)
 
@@ -884,7 +887,7 @@ def rerun_oozie_bundle(request, job_id, app_path):
   oozie_bundle = check_job_access_permission(request, job_id)
   check_job_edition_permission(oozie_bundle, request.user)
   ParametersFormSet = formset_factory(ParameterForm, extra=0)
-  app_path = urllib.unquote(app_path)
+  app_path = urllib.parse.unquote(app_path)
   if request.method == 'POST':
     params_form = ParametersFormSet(request.POST)
     rerun_form = RerunBundleForm(request.POST, oozie_bundle=oozie_bundle)
@@ -926,7 +929,7 @@ def rerun_oozie_bundle(request, job_id, app_path):
     return render('dashboard/rerun_bundle_popup.mako', request, {
                    'rerun_form': rerun_form,
                    'params_form': params_form,
-                   'action': reverse('oozie:rerun_oozie_bundle', kwargs={'job_id': job_id, 'app_path': urllib.quote(app_path.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS)}),
+                   'action': reverse('oozie:rerun_oozie_bundle', kwargs={'job_id': job_id, 'app_path': urllib.parse.quote(app_path.encode('utf-8'), safe=SAFE_CHARACTERS_URI_COMPONENTS)}),
                  }, force_template=True)
 
 
@@ -935,7 +938,7 @@ def _rerun_bundle(request, oozie_id, args, params, properties):
     submission = Submission(user=request.user, fs=request.fs, jt=request.jt, oozie_id=oozie_id, properties=properties)
     job_id = submission.rerun_bundle(params=params, **args)
     return job_id
-  except RestException, ex:
+  except RestException as ex:
     msg = _("Error re-running bundle %s.") % (oozie_id,)
     LOG.exception(msg)
 
@@ -958,7 +961,7 @@ def submit_external_job(request, application_path):
       try:
         submission = Submission(request.user, fs=request.fs, jt=request.jt, properties=mapping)
         job_id = submission.run(application_path)
-      except RestException, ex:
+      except RestException as ex:
         detail = ex._headers.get('oozie-error-message', ex)
         if 'Max retries exceeded with url' in str(detail):
           detail = '%s: %s' % (_('The Oozie server is not running'), detail)
@@ -1170,7 +1173,7 @@ def check_job_access_permission(request, job_id, **kwargs):
         oozie_job = get_job(job_id, **kwargs)
       else:
         oozie_job = get_job(job_id)
-    except RestException, ex:
+    except RestException as ex:
       msg = _("Error accessing Oozie job %s.") % (job_id,)
       LOG.exception(msg)
       raise PopupException(msg, detail=ex._headers.get('oozie-error-message'))

+ 9 - 8
apps/oozie/src/oozie/views/editor.py

@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from builtins import str
 import json
 import logging
 import shutil
@@ -178,7 +179,7 @@ def import_workflow(request):
         _import_workflow(fs=request.fs, workflow=workflow, workflow_definition=workflow_definition)
         request.info(_('Workflow imported'))
         return redirect(reverse('oozie:edit_workflow', kwargs={'workflow': workflow.id}))
-      except Exception, e:
+      except Exception as e:
         request.error(_('Could not import workflow: %s' % e))
         Workflow.objects.destroy(workflow, request.fs)
         raise PopupException(_('Could not import workflow.'), detail=e)
@@ -209,7 +210,7 @@ def import_coordinator(request):
         coordinator.managed = True
         coordinator.name = coordinator_form.cleaned_data.get('name')
         coordinator.save()
-      except Exception, e:
+      except Exception as e:
         request.error(_('Could not import coordinator: %s' % e))
         raise PopupException(_('Could not import coordinator.'), detail=e)
 
@@ -281,8 +282,8 @@ def edit_workflow(request, workflow):
     'default_link_form': DefaultLinkForm(action=workflow.start),
     'node_form': NodeForm(),
     'action_forms': [(node_type, design_form_by_type(node_type, request.user, workflow)())
-                     for node_type in ACTION_TYPES.iterkeys()],
-    'credentials': json.dumps(credentials.credentials.keys())
+                     for node_type in ACTION_TYPES.keys()],
+    'credentials': json.dumps(list(credentials.credentials.keys()))
   })
 
 
@@ -373,7 +374,7 @@ def _submit_workflow(user, fs, jt, workflow, mapping):
     job_id = submission.run()
     History.objects.create_from_submission(submission)
     return job_id
-  except RestException, ex:
+  except RestException as ex:
     detail = ex._headers.get('oozie-error-message', ex)
     if 'Max retries exceeded with url' in str(detail):
       detail = '%s: %s' % (_('The Oozie server is not running'), detail)
@@ -678,7 +679,7 @@ def _submit_coordinator(request, coordinator, mapping):
     History.objects.create_from_submission(submission)
 
     return job_id
-  except RestException, ex:
+  except RestException as ex:
     raise PopupException(_("Error submitting coordinator %s") % (coordinator,),
                          detail=ex._headers.get('oozie-error-message', ex))
 
@@ -891,7 +892,7 @@ def _submit_bundle(request, bundle, properties):
     History.objects.create_from_submission(submission)
 
     return job_id
-  except RestException, ex:
+  except RestException as ex:
     raise PopupException(_("Error submitting bundle %s") % (bundle,),
                          detail=ex._headers.get('oozie-error-message', ex))
 
@@ -938,7 +939,7 @@ def install_examples(request):
       oozie_setup.Command().handle()
       activate_translation(request.LANGUAGE_CODE)
       result['status'] = 0
-    except Exception, e:
+    except Exception as e:
       LOG.exception(e)
       result['message'] = str(e)
 

+ 17 - 16
apps/oozie/src/oozie/views/editor2.py

@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from builtins import str
 import json
 import logging
 
@@ -77,7 +78,7 @@ def open_old_workflow(request):
   try:
     _workflow = import_workflow_from_hue_3_7(workflow)
     return _edit_workflow(request, None, _workflow)
-  except Exception, e:
+  except Exception as e:
     LOG.warn('Could not open old worklow: %s' % smart_str(e))
     return old_edit_workflow(request, workflow=workflow.id)
 
@@ -106,7 +107,7 @@ def _edit_workflow(request, doc, workflow):
 
   try:
     credentials.fetch(api)
-  except Exception, e:
+  except Exception as e:
     LOG.error(smart_str(e))
 
   can_edit_json = doc is None or (doc.can_write(request.user) if USE_NEW_EDITOR.get() else doc.doc.get().is_editable(request.user))
@@ -114,7 +115,7 @@ def _edit_workflow(request, doc, workflow):
   return render('editor2/workflow_editor.mako', request, {
       'layout_json': json.dumps(workflow_data['layout'], cls=JSONEncoderForHTML),
       'workflow_json': json.dumps(workflow_data['workflow'], cls=JSONEncoderForHTML),
-      'credentials_json': json.dumps(credentials.credentials.keys(), cls=JSONEncoderForHTML),
+      'credentials_json': json.dumps(list(credentials.credentials.keys()), cls=JSONEncoderForHTML),
       'workflow_properties_json': json.dumps(WORKFLOW_NODE_PROPERTIES, cls=JSONEncoderForHTML),
       'doc_uuid': doc.uuid if doc else '',
       'subworkflows_json': json.dumps(_get_workflows(request.user), cls=JSONEncoderForHTML),
@@ -314,7 +315,7 @@ def action_parameters(request):
 
     response['status'] = 0
     response['parameters'] = list(parameters)
-  except Exception, e:
+  except Exception as e:
     response['message'] = str(e)
 
   return JsonResponse(response)
@@ -337,7 +338,7 @@ def workflow_parameters(request):
 
     response['status'] = 0
     response['parameters'] = workflow.find_all_parameters(with_lib_path=False)
-  except Exception, e:
+  except Exception as e:
     response['message'] = str(e)
 
   return JsonResponse(response)
@@ -354,7 +355,7 @@ def gen_xml_workflow(request):
 
     response['status'] = 0
     response['xml'] = workflow.to_xml()
-  except Exception, e:
+  except Exception as e:
     response['message'] = str(e)
 
   return JsonResponse(response)
@@ -410,7 +411,7 @@ def _submit_workflow_helper(request, workflow, submit_action):
 
       try:
         job_id = _submit_workflow(request.user, request.fs, request.jt, workflow, mapping)
-      except Exception, e:
+      except Exception as e:
         raise PopupException(_('Workflow submission failed'), detail=smart_str(e), error_code=200)
       jsonify = request.POST.get('format') == 'json'
       if jsonify:
@@ -453,7 +454,7 @@ def _submit_workflow(user, fs, jt, workflow, mapping):
     workflow.document.add_to_history(submission.user, {'properties': submission.properties, 'oozie_id': submission.oozie_id})
 
     return job_id
-  except RestException, ex:
+  except RestException as ex:
     detail = ex._headers.get('oozie-error-message', ex)
     if 'Max retries exceeded with url' in str(detail):
       detail = '%s: %s' % (_('The Oozie server is not running'), detail)
@@ -508,7 +509,7 @@ def edit_coordinator(request):
 
   try:
     credentials.fetch(api)
-  except Exception, e:
+  except Exception as e:
     LOG.error(smart_str(e))
 
   if USE_NEW_EDITOR.get():
@@ -530,7 +531,7 @@ def edit_coordinator(request):
     workflows = [dict([('uuid', d.content_object.uuid), ('name', d.content_object.name)])
                       for d in Document.objects.available_docs(Document2, request.user).filter(extra='workflow2')]
 
-    if coordinator_id and not filter(lambda a: a['uuid'] == coordinator.data['properties']['workflow'], workflows):
+    if coordinator_id and not [a for a in workflows if a['uuid'] == coordinator.data['properties']['workflow']]:
       raise PopupException(_('You don\'t have access to the workflow of this coordinator.'))
 
   if USE_NEW_EDITOR.get(): # In Hue 4, merge with above
@@ -541,7 +542,7 @@ def edit_coordinator(request):
   if request.GET.get('format') == 'json': # For Editor
     return JsonResponse({
       'coordinator': coordinator.get_data_for_json(),
-      'credentials': credentials.credentials.keys(),
+      'credentials': list(credentials.credentials.keys()),
       'workflows': workflows,
       'doc_uuid': doc.uuid if doc else '',
       'is_embeddable': request.GET.get('is_embeddable', False),
@@ -551,7 +552,7 @@ def edit_coordinator(request):
   else:
     return render('editor2/coordinator_editor.mako', request, {
       'coordinator_json': coordinator.to_json_for_html(),
-      'credentials_json': json.dumps(credentials.credentials.keys(), cls=JSONEncoderForHTML),
+      'credentials_json': json.dumps(list(credentials.credentials.keys()), cls=JSONEncoderForHTML),
       'workflows_json': json.dumps(workflows, cls=JSONEncoderForHTML),
       'doc_uuid': doc.uuid if doc else '',
       'is_embeddable': request.GET.get('is_embeddable', False),
@@ -667,7 +668,7 @@ def coordinator_parameters(request):
 
     response['status'] = 0
     response['parameters'] = coordinator.find_all_parameters(with_lib_path=False)
-  except Exception, e:
+  except Exception as e:
     response['message'] = str(e)
 
   return JsonResponse(response)
@@ -693,7 +694,7 @@ def submit_coordinator(request, doc_id):
       jsonify = request.POST.get('format') == 'json'
       try:
         job_id = _submit_coordinator(request, coordinator, mapping)
-      except Exception, e:
+      except Exception as e:
         message = force_unicode(str(e))
         return JsonResponse({'status': -1, 'message': message}, safe=False)
       if jsonify:
@@ -781,7 +782,7 @@ def _submit_coordinator(request, coordinator, mapping):
     job_id = submission.run()
 
     return job_id
-  except RestException, ex:
+  except RestException as ex:
     LOG.exception('Error submitting coordinator')
     raise PopupException(_("Error submitting coordinator %s") % (coordinator,), detail=ex._headers.get('oozie-error-message', ex), error_code=200)
 
@@ -973,6 +974,6 @@ def _submit_bundle(request, bundle, properties):
     job_id = submission.run()
 
     return job_id
-  except RestException, ex:
+  except RestException as ex:
     LOG.exception('Error submitting bundle')
     raise PopupException(_("Error submitting bundle %s") % (bundle,), detail=ex._headers.get('oozie-error-message', ex), error_code=200)