import sys import traceback import copy import string import inspect verbose_enable = False debug_dict = dict() # constantly-changing variables, for visual debug def get_verbose_enable(): return verbose_enable def set_verbose_enable(enable): global verbose_enable print("[ common.py ] NOTE: set verbose: " + str(enable)) verbose_enable = enable class ScopeInfo: indent = None name = None line_number = -1 def get_yaml_from_literal_value(val): # TODO: add yaml escape sequences (see expertmm MoneyForesight for example) if type(val).__name__ == "string": val = "\"" + val.replace("\"", "\\\"") + "\"" else: val = str(val) return val def get_literal_value_from_yaml(val): # TODO: process yaml escape sequences (see expertmm MoneyForesight for example) val=val.strip() if len(val)>2: if val[0:1]=="\"" and val[-1:]=="\"": val=val[1:-1] return val #from github.com/expertmm/minetest/chunkymap/expertmm.py, but modified for python2 def get_dict_deepcopy(old_dict, depth=0): new_dict = None if type(old_dict) is dict: new_dict = {} for this_key in old_dict.keys(): try: new_dict[this_key] = copy.deepcopy(old_dict[this_key]) except: try: new_dict[this_key] = old_dict[this_key].copy(depth=depth+1) except: try: new_dict[this_key] = old_dict[this_key].copy() except: new_dict[this_key] = old_dict[this_key] return new_dict valid_path_name_chars = "-_.() %s%s" % (string.ascii_letters, string.digits) if verbose_enable: print("[ common.py ] (verbose message) Using valid_path_name_chars: '" + \ valid_path_name_chars + "'") def find_any_not(haystack, needles): result = -1 for i in range(len(haystack)): if haystack[i:i+1] not in needles: result = i break return result def good_path_name(try_path_name): result = "" if try_path_name is not None: for i in range(len(try_path_name)): if try_path_name[i:i+1] not in valid_path_name_chars: result += "_" else: result += try_path_name[i:i+1] else: result = None return result # displays 2D array in fixed-width format as string result with # newline characters in between each row # (uses fixed_width function on each row) def fixed_widths(val_lists, visible_width, spacing): result = "" delim = "" for vals in val_lists: result += fixed_width(vals, visible_width, spacing) delim = "\n" return result fixed_width_warnings = {} # makes each column visible_width characters wide, sacrificing extra # characters at end. # spacing is added between columns # so total width of each column plus spacing (except for last column) # would be visible_width + len(spacing) def fixed_width(vals, visible_width, spacing): result = "" fixed_width = visible_width + len(spacing) for original_val in vals: val = str(original_val) if result != "": result += spacing if len(val) < visible_width: val += " " * (visible_width - len(val)) else: if "." in val[fixed_width:]: curframe = inspect.currentframe() calframe = inspect.getouterframes(curframe, 2) fixed_width_warnings[calframe[1][3]] = True if not calframe[1][3] in fixed_width_warnings: # raise ValueError print("[ common.py ] ERROR: fixed width " + str(fixed_width) + " is too small" + "--missed significant figures in " + str(val) + " (sender: " + calframe[1][3] + ")" ) result += val[:fixed_width] return result def view_traceback(indent=""): ex_type, ex, tb = sys.exc_info() print(indent + str(ex_type) + " " + str(ex) + ": ") traceback.print_tb(tb) del tb print("") def get_traceback(indent=""): ex_type, ex, tb = sys.exc_info() result = indent + str(ex_type) + " " + str(ex) + ": " + "\n" #traceback.print_tb(tb) result += str(tb) del tb return result def get_by_name(object_list, needle): # formerly find_by_name result = None for i in range(0,len(object_list)): try: if object_list[i].name == needle: result = object_list[i] break except: #e = sys.exc_info()[0] #print("Could not finish get_by_name:" + str(e)) print("[ common.py ] ERROR--Could not finish get_by_name:") view_traceback() return result def find_by_name(object_list, needle): result = -1 for i in range(0,len(object_list)): try: if object_list[i].name == needle: result = i break except: #e = sys.exc_info()[0] #print("Could not finish get_by_name:" + str(e)) print("[ common.py ] ERROR--Could not finish find_by_name:") view_traceback() return result def push_yaml_text(yaml, name, val, indent): if type(val) is dict: for key in val.keys(): yaml = push_yaml_text(yaml, key, val[key], indent+" ") else: #if val is None: #if yaml is not None: # if len(yaml)>0: # yaml += "\n" #else: # yaml = "" if yaml is None: yaml = "" if val is None: yaml += indent + name + ": ~" else: yaml += indent + name + ": " + str(val) yaml += "\n" return yaml true_like_strings = ['true', 'yes', 'on', '1'] def set_true_like_strings(vals): global true_like_strings set_enable = True for tls in vals: if tls.lower() != tls: set_enable = False print("[ common.py ] ERROR: refusing to set true_like_strings" + \ " since an element contains uppercase characters") break if set_enable: true_like_strings = vals # Only returns True if `is True`, `== 1`, or # lower().strip() in true_like_strings def is_true(val): result = False try: val_lower = None try: val_lower = val.lower() except: pass if val_lower is not None: # is string val_lower = val_lower.strip() if val_lower in true_like_strings: result = True elif val_lower is True: result = True elif val == 1: result = True except: print("[ common.py ] ERROR--Could not finish is_true" + \ " (returning false):") view_traceback() return result