Clone of official tools

Revision:
43:2a7da56ebd24
Parent:
36:96847d42f010
--- a/utils.py	Mon Nov 06 13:17:14 2017 -0600
+++ b/utils.py	Tue Sep 25 13:43:09 2018 -0500
@@ -14,6 +14,7 @@
 See the License for the specific language governing permissions and
 limitations under the License.
 """
+from __future__ import print_function, division, absolute_import
 import sys
 import inspect
 import os
@@ -30,6 +31,11 @@
 import logging
 from intelhex import IntelHex
 
+try:
+    unicode
+except NameError:
+    unicode = str
+
 def remove_if_in(lst, thing):
     if thing in lst:
         lst.remove(thing)
@@ -66,14 +72,14 @@
     """A wrapper to run a command as a blocking job"""
     text = command if shell else ' '.join(command)
     if verbose:
-        print text
+        print(text)
     return_code = call(command, shell=shell, cwd=cwd)
     if check and return_code != 0:
         raise Exception('ERROR %d: "%s"' % (return_code, text))
 
 
 def run_cmd(command, work_dir=None, chroot=None, redirect=False):
-    """Run a command in the forground
+    """Run a command in the foreground
 
     Positional arguments:
     command - the command to run
@@ -100,7 +106,7 @@
                         stderr=STDOUT if redirect else PIPE, cwd=work_dir)
         _stdout, _stderr = process.communicate()
     except OSError:
-        print "[OS ERROR] Command: "+(' '.join(command))
+        print("[OS ERROR] Command: "+(' '.join(command)))
         raise
 
     return _stdout, _stderr, process.returncode
@@ -173,6 +179,27 @@
         makedirs(path)
 
 
+def write_json_to_file(json_data, file_name):
+    """
+    Write json content in file
+    :param json_data:
+    :param file_name:
+    :return:
+    """
+    # Create the target dir for file if necessary
+    test_spec_dir = os.path.dirname(file_name)
+
+    if test_spec_dir:
+        mkdir(test_spec_dir)
+
+    try:
+        with open(file_name, 'w') as f:
+            f.write(json.dumps(json_data, indent=2))
+    except IOError as e:
+        print("[ERROR] Error writing test spec to file")
+        print(e)
+
+
 def copy_file(src, dst):
     """ Implement the behaviour of "shutil.copy(src, dst)" without copying the
     permissions (this was causing errors with directories mounted with samba)
@@ -199,7 +226,7 @@
     for element in listdir(directory):
         to_remove = join(directory, element)
         if not isdir(to_remove):
-            remove(file)
+            remove(to_remove)
 
 
 def get_caller_name(steps=2):
@@ -318,38 +345,19 @@
             except ImportError as exc:
                 not_installed_modules.append(module_name)
                 if verbose:
-                    print "Error: %s" % exc
+                    print("Error: %s" % exc)
 
     if verbose:
         if not_installed_modules:
-            print ("Warning: Module(s) %s not installed. Please install " + \
-                   "required module(s) before using this script.")\
-                % (', '.join(not_installed_modules))
+            print("Warning: Module(s) %s not installed. Please install "
+                  "required module(s) before using this script."
+                  % (', '.join(not_installed_modules)))
 
     if not_installed_modules:
         return False
     else:
         return True
 
-def dict_to_ascii(dictionary):
-    """ Utility function: traverse a dictionary and change all the strings in
-    the dictionary to ASCII from Unicode. Useful when reading ASCII JSON data,
-    because the JSON decoder always returns Unicode string. Based on
-    http://stackoverflow.com/a/13105359
-
-    Positional arguments:
-    dictionary - The dict that contains some Unicode that should be ASCII
-    """
-    if isinstance(dictionary, dict):
-        return OrderedDict([(dict_to_ascii(key), dict_to_ascii(value))
-                            for key, value in dictionary.iteritems()])
-    elif isinstance(dictionary, list):
-        return [dict_to_ascii(element) for element in dictionary]
-    elif isinstance(dictionary, unicode):
-        return dictionary.encode('ascii')
-    else:
-        return dictionary
-
 def json_file_to_dict(fname):
     """ Read a JSON file and return its Python representation, transforming all
     the strings from Unicode to ASCII. The order of keys in the JSON file is
@@ -360,8 +368,8 @@
     """
     try:
         with open(fname, "r") as file_obj:
-            return dict_to_ascii(json.load(file_obj,
-                                           object_pairs_hook=OrderedDict))
+            return json.loads(file_obj.read().encode('ascii', 'ignore'),
+                              object_pairs_hook=OrderedDict)
     except (ValueError, IOError):
         sys.stderr.write("Error parsing '%s':\n" % fname)
         raise
@@ -375,6 +383,8 @@
             the string, or the hyphens/underscores do not match the expected
             style of the argument.
             """
+            if not isinstance(string, unicode):
+                string = string.decode()
             if prefer_hyphen:
                 newstring = casedness(string).replace("_", "-")
             else:
@@ -393,10 +403,10 @@
     return middle
 
 # short cuts for the argparse_type versions
-argparse_uppercase_type = argparse_type(str.upper, False)
-argparse_lowercase_type = argparse_type(str.lower, False)
-argparse_uppercase_hyphen_type = argparse_type(str.upper, True)
-argparse_lowercase_hyphen_type = argparse_type(str.lower, True)
+argparse_uppercase_type = argparse_type(unicode.upper, False)
+argparse_lowercase_type = argparse_type(unicode.lower, False)
+argparse_uppercase_hyphen_type = argparse_type(unicode.upper, True)
+argparse_lowercase_hyphen_type = argparse_type(unicode.lower, True)
 
 def argparse_force_type(case):
     """ validate that an argument passed in (as string) is a member of the list
@@ -404,8 +414,12 @@
     """
     def middle(lst, type_name):
         """ The parser type generator"""
+        if not isinstance(lst[0], unicode):
+            lst = [o.decode() for o in lst]
         def parse_type(string):
             """ The parser type"""
+            if not isinstance(string, unicode):
+                string = string.decode()
             for option in lst:
                 if case(string) == case(option):
                     return option
@@ -416,8 +430,8 @@
     return middle
 
 # these two types convert the case of their arguments _before_ validation
-argparse_force_uppercase_type = argparse_force_type(str.upper)
-argparse_force_lowercase_type = argparse_force_type(str.lower)
+argparse_force_uppercase_type = argparse_force_type(unicode.upper)
+argparse_force_lowercase_type = argparse_force_type(unicode.lower)
 
 def argparse_many(func):
     """ An argument parser combinator that takes in an argument parser and
@@ -529,3 +543,11 @@
         raise ToolException("File %s does not have a known binary file type"
                             % filename)
     return ih
+
+
+def integer(maybe_string, base):
+    """Make an integer of a number or a string"""
+    if isinstance(maybe_string, int):
+        return maybe_string
+    else:
+        return int(maybe_string, base)