Port Bake to Python 3
authorAnkit Deepak <adadeepak8@gmail.com>
Wed, 24 Feb 2016 16:54:10 -0800
changeset 362 c8a14ad2a984
parent 361 fda0b365e4eb
child 363 d037e7d47505
Port Bake to Python 3
bake/Bake.py
bake/Configuration.py
bake/Dependencies.py
bake/Exceptions.py
bake/Module.py
bake/ModuleBuild.py
bake/ModuleEnvironment.py
bake/ModuleSource.py
bake/Utils.py
bakeconf.xml
--- a/bake/Bake.py	Mon Feb 08 11:03:35 2016 -0800
+++ b/bake/Bake.py	Wed Feb 24 16:54:10 2016 -0800
@@ -773,12 +773,12 @@
                     sys.stdout.write (" >> Downloading " + module.name() + targetDir + " - ")
                 sys.stdout.flush()
                 if env._logger._verbose > 0:
-                    print
+                    print()
 
                 env._sudoEnabled=options.call_with_sudo
                 ModuleEnvironment._stopOnError=options.stopOnError
                 valueToReturn=module.check_source_version(env)
-            
+
             
                 if valueToReturn: 
                     return module.download(env, options.force_download)
@@ -823,7 +823,7 @@
                 sys.stdout.write (" >> Updating " + module.name() + targetDir + " - ")
             sys.stdout.flush()
             if env._logger._verbose > 0:
-                print
+                print()
                 
             return module.update(env)
 
@@ -1016,12 +1016,12 @@
             else:
                 colorTool.cPrintln(colorTool.WARNING, " > " + element[1] + 
                                  " - is missing")
-        print
+        print ('\n')
         colorTool.cPrint(colorTool.OK, " > Path searched for tools:")
         for item in env.path_list():
             sys.stdout.write (' ' + item)
             sys.stdout.flush()
-        print
+        print ('\n')
           
     def _get_dummy_env(self, options):
         """ Returns a dummy environment just for verifying the user's system configuration. """
@@ -1230,7 +1230,7 @@
         padding = padding + ' '
         
         # to avoid loops
-        if has_passed.has_key(key):
+        if key in has_passed:
             sys.stdout.write(padding)
             ColorTool.cPrintln(ColorTool.FAIL, "> Cyclic Dependency")
             return "> Cyclic Dependency."
@@ -1249,7 +1249,7 @@
             print (padding + '|')
             optional=""
             color=ColorTool.FAIL
-            if depen.has_key(this_key) and isinstance(depen[this_key],bool)>0:
+            if this_key in depen and isinstance(depen[this_key],bool)>0:
                 if depen[this_key]:
                     optional = " (optional)"
                     color=ColorTool.OK
--- a/bake/Configuration.py	Mon Feb 08 11:03:35 2016 -0800
+++ b/bake/Configuration.py	Wed Feb 24 16:54:10 2016 -0800
@@ -197,7 +197,7 @@
         # get list of names in <attribute name="" value=""> tags
         attributes_present = [child.get('name') for child in node.findall('attribute')]
         # get list of names in <type_string name="value"> attributes
-        attributes_present = attributes_present + node.attrib.keys()
+        attributes_present = attributes_present + list(node.attrib)
         
         for attribute in attribute_base.attributes():
             if attribute.is_mandatory and not attribute.name in attributes_present:
@@ -252,7 +252,7 @@
                 
             classname = node.get('classname')
             import codeop
-            exec code_node.text in globals(), locals()
+            exec(code_node.text, globals(), locals())
             obj = eval(classname + '()')
             obj.__hidden_source_code = code_node.text
         else:
--- a/bake/Dependencies.py	Mon Feb 08 11:03:35 2016 -0800
+++ b/bake/Dependencies.py	Wed Feb 24 16:54:10 2016 -0800
@@ -53,7 +53,7 @@
     def __init__(self):
         return
 
-class DependencyUnmet:
+class DependencyUnmet(Exception):
     def __init__(self, failed, method=''):
         self._failed = failed
         self._method = method
@@ -97,7 +97,7 @@
     def src(self):
         return self._src
     def is_src_optional(self,src):
-        assert self._optional.has_key(src)
+        assert src in self._optional
         return self._optional[src]
     def context(self):
         return self._context
@@ -125,7 +125,7 @@
         if isinstance(dst,list):
             return [self.add_dst(d,context) for d in dst]
         # the dependency is already recorded. nothing to do.
-        if self._targets.has_key(dst):
+        if dst in self._targets:
             return
         # update dependency information
         target = Target(dst, context)
@@ -139,7 +139,7 @@
         # if the dependence is in fact for a list of dependencies
         if isinstance(src,list):
             return [self.add_dep(s,dst) for s in src]
-        assert self._targets.has_key(dst)
+        assert dst in self._targets
         # the dependency is already recorded. nothing to do.
         target = self._targets[dst]
         if src in target.src ():
@@ -148,7 +148,7 @@
         # record new dependency
         target = self._targets[dst]
         target.add_src(src, optional)
-        if not self._sources.has_key(src):
+        if not src in self._sources:
             self._sources[src] = [target]
         elif target not in self._sources[src]:
             self._sources[src].append(target)
@@ -221,7 +221,7 @@
             i = workqueue.pop()
             if i not in deps:
                 deps.append(i)
-            if self._sources.has_key(i.dst()):
+            if i.dst() in self._sources:
                 workqueue.extend(self._sources[i.dst()])
         return deps
 
@@ -233,7 +233,7 @@
         # XXX: should detect cycles here.
         workqueue = [self._targets[target] 
                      for target in targets 
-                        if self._targets.has_key(target)]
+                        if target in self._targets]
         
         deps = []
         while len(workqueue) > 0:
@@ -242,19 +242,19 @@
                 deps.append(i)
 
             for src in i.src():
-                if self._targets.has_key(src):
+                if src in self._targets:
                     workqueue.append(self._targets[src])
         return deps
 
     def _is_leaf(self, target):
         """ Verifies if the target is independent of any module."""
         
-        assert self._targets.has_key(target.dst())
+        assert target.dst() in self._targets
         # a 'leaf' is a target which either has
         # no source or whose sources are not
         # targets themselves.
         for src in target.src():
-            if self._targets.has_key (src):
+            if src in self._targets:
                 return False
         return True
 
@@ -282,7 +282,7 @@
         # priority.
         while len(workqueue) > 0:
             source = workqueue.pop()
-            if not self._sources.has_key (source.dst()):
+            if not source.dst() in self._sources:
                 continue
             for dst in self._sources[source.dst()]:
                 if dst not in to_resolve:
@@ -294,20 +294,39 @@
         # we want to find the list of targets for each priority
         prio_inverted = dict()
         for target in to_resolve:
-            if prio_inverted.has_key(prio[target]):
+            if prio[target] in prio_inverted:
                 prio_inverted[prio[target]].append(target)
             else:
                 prio_inverted[prio[target]] = [target]
-                
+               
         # generate a sorted list of targets, lowest-priority first
         sorted_targets = []
         for key in sorted(prio_inverted.keys()):
-            sorted_targets.extend(sorted(prio_inverted[key], self._cmp))
+            sorted_targets.extend(sorted(prio_inverted[key], key=self.cmp_to_key(self._cmp)))
         # convert the list of targets into a list of steps
         return sorted_targets
+    def cmp_to_key(self, mycmp):
+        'Convert a cmp= function into a key= function'
+        class K(object):
+            def __init__(self, obj, *args):
+                self.obj = obj
+            def __lt__(self, other):
+                return mycmp(self.obj, other.obj) < 0
+            def __gt__(self, other):
+                return mycmp(self.obj, other.obj) > 0
+            def __eq__(self, other):
+                return mycmp(self.obj, other.obj) == 0
+            def __le__(self, other):
+                return mycmp(self.obj, other.obj) <= 0
+            def __ge__(self, other):
+                return mycmp(self.obj, other.obj) >= 0
+            def __ne__(self, other):
+                return mycmp(self.obj, other.obj) != 0
+        return K
+
 
     def _cmp(self, a, b):
-        return cmp(a.dst(), b.dst());
+        return (id(b.dst())-id(a.dst()));
 
     def _is_clean(self,targets):
         """ Returns true if the target is clean, resolved, and False if it 
@@ -315,7 +334,7 @@
         """
 
         for target in targets:
-            if self._targets.has_key (target):
+            if target in self._targets:
                 if self._targets[target].is_dirty():
                     return False
         return True
@@ -341,7 +360,7 @@
                     success = i.context()()
                 except TaskError as e:
                     success = False
-                    print ("  > Error: " + e._reason)
+                    print("  > Error: " + e._reason)
 #                except SystemExit as e:
 #                    print(sys.exc_info())
 #
@@ -351,7 +370,7 @@
                     success = False
                     import sys
                     er = sys.exc_info()[1]
-                    print ("  > Error: " + str(er))
+                    print("  > Error: " + str(er))
                     from bake.ModuleEnvironment import ModuleEnvironment
                     if ModuleEnvironment._stopOnError:
                         er = sys.exc_info()[1]
@@ -362,7 +381,7 @@
                     success = callback(i.dst(), i.context())
                 except TaskError as e:
                     success = False
-                    print ("  > Error: " + e._reason)
+                    print("  > Error: " + e._reason)
                     from bake.ModuleEnvironment import ModuleEnvironment
                     if ModuleEnvironment._stopOnError:
                         er = sys.exc_info()[1]
@@ -371,13 +390,13 @@
                     success = False
                     import sys
                     er = sys.exc_info()[1]
-                    print ("  > Unexpected error: " + str(er))
+                    print("  > Unexpected error: " + str(er))
                     from bake.ModuleEnvironment import ModuleEnvironment
                     if ModuleEnvironment._stopOnError:
                         er = sys.exc_info()[1]
                         sys.exit(1)
             if not success:
-                if not self._sources.has_key(i.dst()):
+                if not i.dst() in self._sources:
                     raise DependencyUnmet(i.dst())
                 else:
                     for j in self._sources[i.dst()]:
@@ -393,7 +412,7 @@
                             
                             if not self.dependencies[i.dst()._name].moduleProblem:
                                 
-                                print (' > Problem: Optional dependency,'
+                                print(' > Problem: Optional dependency,'
                                              ' module "%s" %s\n'
                                              '   This may reduce the  '
                                              'functionality of the final build. \n'
--- a/bake/Exceptions.py	Mon Feb 08 11:03:35 2016 -0800
+++ b/bake/Exceptions.py	Wed Feb 24 16:54:10 2016 -0800
@@ -23,7 +23,7 @@
  This file stores the Exceptions raised by Bake.
 ''' 
 
-class TaskError:
+class TaskError(Exception):
     """ Error found during the execution of the required options. """
     
     def __init__(self, reason = ''):
@@ -33,7 +33,7 @@
     def reason(self):
         return self._reason
 
-class MetadataError:
+class MetadataError(Exception):
     """ Error reading the configuration. """
     
     def __init__(self, reason = ''):
@@ -42,7 +42,7 @@
     def reason(self):
         return self._reason
 
-class NotImplemented:
+class NotImplemented(Exception):
     """ A not yet implemented option was met. """
     
     def __init__(self):
--- a/bake/Module.py	Mon Feb 08 11:03:35 2016 -0800
+++ b/bake/Module.py	Wed Feb 24 16:54:10 2016 -0800
@@ -98,7 +98,7 @@
             color=colorTool.FAIL
             
         if env._logger._verbose > 0:
-            print
+            print()
             colorTool.cPrintln(color, " >> " + operation + " " + 
                                     self._name + " - " +resultStr)
         else:
@@ -490,7 +490,6 @@
         srcDirTmp = self._name
         if self._source.attribute('module_directory').value :
             srcDirTmp = self._source.attribute('module_directory').value
-
         env.start_source(self._name, srcDirTmp)
         retval = self._source.check_version(env)
         env.end_source()
--- a/bake/ModuleBuild.py	Mon Feb 08 11:03:35 2016 -0800
+++ b/bake/ModuleBuild.py	Wed Feb 24 16:54:10 2016 -0800
@@ -28,7 +28,12 @@
 import bake.Utils
 import os
 import platform
-import commands
+import subprocess
+try:
+    import commands
+    from commands import getstatusoutput, getoutput
+except ImportError:
+    from subprocess import getstatusoutput, getoutput
 import re
 import sys
 import shlex
@@ -133,11 +138,11 @@
             for comandToExecute in commandList :
                 try:
                     env._logger.commands.write("    > " +env.replace_variables(comandToExecute)+ '\n');
-                    resultStatus = commands.getstatusoutput(env.replace_variables(comandToExecute))
+                    resultStatus = getstatusoutput(env.replace_variables(comandToExecute))
                     if(resultStatus[0] == 0) :
                         return True
                 except Exception as e:
-                    print ("   > Error executing pre installation : " + e + "\n")
+                    print ("   > Error executing pre installation : " + str(e) + "\n")
 
         return False
     
@@ -147,7 +152,7 @@
         if self.attribute('post_installation').value != '':
             try:
                 env._logger.commands.write(" > " + env.replace_variables(self.attribute('post_installation').value))
-                var = commands.getoutput(env.replace_variables(self.attribute('post_installation').value))
+                var = getoutput(env.replace_variables(self.attribute('post_installation').value))
                 
                 if env.debug:
                     print("  -> " +  var)
@@ -173,7 +178,7 @@
 
             try:
                 env._logger.commands.write('cd ' + env.srcdir + '; patch -p1 < ' + item + '\n')
-                status = commands.getstatusoutput('cd ' + env.srcdir + '; patch -p1 < ' + item) 
+                status = getstatusoutput('cd ' + env.srcdir + '; patch -p1 < ' + item) 
             except:
                 raise TaskError('Patch error: %s, in: %s' % (item, env._module_name))
             
@@ -389,7 +394,7 @@
         """ Searches for the waf version, it should be bigger than 1.6.0."""
         
         return env.check_program(self._binary(env.srcdir), version_arg='--version',
-                                 version_regexp='(\d+)\.(\d+)\.(\d+)',
+                                 version_regexp=b'(\d+)\.(\d+)\.(\d+)',
                                  version_required=(1, 6, 0))
         
     def build(self, env, jobs):
@@ -470,7 +475,7 @@
         
         for path in [os.path.join(env.srcdir, 'waf'), 'waf']:
             if env.check_program(path, version_arg='--version',
-                                 version_regexp='(\d+)\.(\d+)\.(\d+)',
+                                 version_regexp=b'(\d+)\.(\d+)\.(\d+)',
                                  version_required=(1, 5, 9)):
                 return True
             
@@ -596,12 +601,12 @@
         """ Verifies if CMake and Make are available and their versions."""
 
         if not env.check_program('cmake', version_arg='--version',
-                                 version_regexp='(\d+)\.(\d+)\.(\d+)',
+                                 version_regexp=b'(\d+)\.(\d+)\.(\d+)',
                                  version_required=(2, 8, 2)):
             return False
         
         if not env.check_program('make', version_arg='--version',
-                                 version_regexp='(\d+)\.(\d+)',
+                                 version_regexp=b'(\d+)\.(\d+)',
                                  version_required=(3, 80)):
             return False
         
@@ -707,7 +712,7 @@
                 return True
 
         if not env.check_program('make', version_arg='--version',
-                                 version_regexp='(\d+)\.(\d+)',
+                                 version_regexp=b'(\d+)\.(\d+)',
                                  version_required=(3, 80)):
             return False
         return True
@@ -821,12 +826,12 @@
         """ Verifies if Autoreconf and Make are available and their versions."""
 
         if not env.check_program('autoreconf', version_arg='--version',
-                                 version_regexp='(\d+)\.(\d+)',
+                                 version_regexp=b'(\d+)\.(\d+)',
                                  version_required=(2, 13)):
             return False
         
         if not env.check_program('make', version_arg='--version',
-                                 version_regexp='(\d+)\.(\d+)',
+                                 version_regexp=b'(\d+)\.(\d+)',
                                  version_required=(3, 80)):
             return False
         
--- a/bake/ModuleEnvironment.py	Mon Feb 08 11:03:35 2016 -0800
+++ b/bake/ModuleEnvironment.py	Wed Feb 24 16:54:10 2016 -0800
@@ -148,7 +148,7 @@
                     'FreeBSD' : 'LD_LIBRARY_PATH',
                     'Darwin' : 'DYLD_LIBRARY_PATH',
                     'Windows' : 'PATH'}
-        if not lib_var.has_key(platform.system()):
+        if not platform.system() in lib_var:
             sys.stderr('Error: Unsupported platform. Send email to ' 
                        'bake_support@inria.fr (%s)' % platform.system())
             sys.exit(1)
@@ -179,7 +179,7 @@
     def _append_path(self, d, name, value, sep):
         ''' Append the variable to the system in use configuration. '''
         
-        if not d.has_key(name):
+        if not name in d:
             d[name] = value
         else:
             d[name] = d[name] + sep + value
@@ -403,7 +403,7 @@
         fout = open(fileName, "w")
         fout.write(script)
         fout.close()
-        os.chmod(fileName, 0755)
+        os.chmod(fileName, 0o755)
         
         return script
         
@@ -510,7 +510,7 @@
             stdout = sys.stdout
             stderr = sys.stderr      
                   
-        tmp = dict(os.environ.items() + env.items())
+        tmp = dict(list(os.environ.items()) + list(env.items()))
         
         # sets the library and binary paths 
         tmp = self.append_to_path(tmp)
--- a/bake/ModuleSource.py	Mon Feb 08 11:03:35 2016 -0800
+++ b/bake/ModuleSource.py	Wed Feb 24 16:54:10 2016 -0800
@@ -24,14 +24,20 @@
  the handled source code repository tools. It is this class that defines how 
  a download of a zip file, or a mercurial repository will be made.  
 ''' 
+import urllib
+try:
+    from urllib.parse import urlparse
+    from urllib.request import urlretrieve
+except ImportError:
+    from urlparse import urlparse
+    from urllib import urlretrieve
 import bake.Utils
 from bake.Exceptions import TaskError
 from bake.Utils import ModuleAttributeBase
 import os
-import urlparse
 import re
 import platform
-import commands
+import subprocess
 from datetime import date
 
 class ModuleSource(ModuleAttributeBase):
@@ -117,7 +123,7 @@
         else:
             distribution = osName
         
-        if tools.has_key(distribution):
+        if distribution in tools:
             return tools[distribution]
         else :
             return ''
@@ -299,7 +305,6 @@
         
     def check_version(self, env):
         """ Checks if the tool is available and with the needed version."""
-        
         return env.check_program('bzr', version_arg='--version',
                                  version_regexp='(\d+)\.(\d+)',
                                  version_required=(2, 1))
@@ -341,7 +346,6 @@
         
     def check_version(self, env):
         """ Checks if the tool is available and with the needed version."""
-
         return env.check_program('hg')
 
 
@@ -422,16 +426,14 @@
     def download(self, env):
         """Downloads the specific file."""
         
-        import urllib
-        import urlparse
-        import os
+
          
         url_local = self.attribute('url').value
        
-        filename = os.path.basename(urlparse.urlparse(url_local).path)
+        filename = os.path.basename(urlparse(url_local).path)
         tmpfile = os.path.join(env.srcrepo, filename)
         try:
-            urllib.urlretrieve(url_local, filename=tmpfile)
+            urlretrieve(url_local, filename=tmpfile)
         except IOError as e:
             raise TaskError('Download problem for module: %s, URL: %s, Error: %s' 
                             % (env._module_name,self.attribute('url').value, e))
@@ -443,10 +445,10 @@
         pass
 
     def check_version(self, env):
+
         """Verifies if the right program exists in the system to handle the
          given compressed source file.
          """
-        
         extensions = [
             ['tar', 'tar'],
             ['tar.gz', 'tar'],
@@ -460,7 +462,7 @@
             ['Z', 'uncompress']
             ]
         try:
-            filename = os.path.basename(urlparse.urlparse(self.attribute('url').value).path)
+            filename = os.path.basename(urlparse(self.attribute('url').value).path)
         except AttributeError as e:
             return False
 
@@ -911,5 +913,4 @@
 
     def check_version(self, env):
         """ Checks if the tool is available and with the needed version."""
-
         return env.check_program('git')
--- a/bake/Utils.py	Mon Feb 08 11:03:35 2016 -0800
+++ b/bake/Utils.py	Wed Feb 24 16:54:10 2016 -0800
@@ -189,7 +189,7 @@
     def add_attribute(self, name, value, help, mandatory = False):
         """ Creates a new attribute attached to this one."""
        
-        assert not self._attributes.has_key(name)
+        assert not name in self._attributes
         self._attributes[name] = ModuleAttribute(name, value, help, mandatory)
         
     def attributes(self):
@@ -200,7 +200,7 @@
     def attribute(self, name):
         """ Returns a specific attribute."""
         
-        if not self._attributes.has_key(name):
+        if not name in self._attributes:
             return None
         else:
             return self._attributes[name]
--- a/bakeconf.xml	Mon Feb 08 11:03:35 2016 -0800
+++ b/bakeconf.xml	Wed Feb 24 16:54:10 2016 -0800
@@ -907,8 +907,8 @@
         env._logger.commands.write("LibDir: " + srcLib +"\n")
         destination = os.path.join(env.installdir, 'lib')
         env._logger.commands.write("DstDir: " + destination +"\n")
-	if not os.path.exists(destination):
-    		os.makedirs(destination)
+        if not os.path.exists(destination):
+            os.makedirs(destination)
         files = os.listdir(srcLib)
         env._logger.commands.write("Files:"+str(files)+"\n")
         for file in files: