Sublime Text - Pluign for testing and debuggin __init__.py files • Code • My__init__test
Jul 31, 20247 min read
How to make it work
Find your Sublime Text/User Folder, it should be somenthing like: C:\Users\Uomocosa\AppData\Roaming\Sublime Text\Packages\User.
Create two new files:
My__init__test.sublime-build
My__init__test.py
Create at least a folder called “test_1_” in the correct path, inside this folder you can create some simple python package strucutre, with blank “__init__.py” files.
Then create a new “*__init__to_copy.py*” file, this will be the file that will get copied to all instances of the other “__init__.py” files, in onether new folder, taking “test_1_” as template.
In Sublime Text go to: Tools >> Build System >> My__init__test, and build it. ==NOTE: There is a section in the code of the My__init__test.py file that need to be edited, specifically you need to define the corrects paths to the folders.==
My__init__test.sublime-build
{ "target": "my__init__test", //Refering to: My__init__testCommand // "name": "build ALL executable files", "selector": "source.python", "cmd": ["py", "-u", "$file"], "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)", "env": {"PYTHONIOENCODING": "utf-8"}, "encoding": "utf-8", "variants": [ { "name": "build only the FIRST executable file", "variant_id": "001", }, ]}
My__init__test.py
import sublimeimport sublime_pluginimport subprocessimport osimport pathlibimport shutilimport timeDEBUG = Truedef D(debug_message): if DEBUG: print(">>> "+debug_message) # ---------------------- Changables -----------------------------ALLOWED_FILE_NAMES = ["__init__to_be_copied", "__init__da_copiare"]FOLDER_TO_SAVE_TEST_SUBFOLDERS = { 'Simone-PC': "C:\\Users\\acer\\Desktop\\Samuele\\Syncthing\\LWF - LightWeigth Folder\\[P] Python\\Various Tests\\Test_Various_inits", 'Uomocsa-PC': "D:\\Program Files (x86)\\Syncthing\\LWF - LightWeigth Folder\\[P] Python\\Various Tests\\Test_Various_inits",}TEMPLATE_TEST_FOLDERS = { 'Simone-PC': "C:\\Users\\acer\\AppData\\Roaming\\Sublime Text\\Packages\\User\\my__init__test_folders", 'Uomocsa-PC': "C:\\Users\\Uomocosa\\AppData\\Roaming\\Sublime Text\\Packages\\User\\my__init__test_folders",}EXECUTABLE_FILE_EXTENSIONS = [".py"]EXCLUDE_THESE_EXECUTABLE_FILES = ["__init__.py"]CURRENT_PC = None# ---------------------- ---------- -----------------------------list_of_PCs = list(FOLDER_TO_SAVE_TEST_SUBFOLDERS.keys())# D(f"list_of_PCs = {list_of_PCs}")class My__init__testCommand(sublime_plugin.WindowCommand): def run(self, **kwargs): current_PC = get_current_pc() D(f"current_PC = {current_PC}") __init__file_path = kwargs['cmd'][2] assert_correct_file_name(__init__file_path) save_folder_path = FOLDER_TO_SAVE_TEST_SUBFOLDERS[current_PC] new_Test_folder_path = create_new_Test_folder() add_test = lambda test_folder_name : add_modified_subtest_folder_to_folder( destination_test_folder=new_Test_folder_path, subtest_folder_name=test_folder_name, new__init__file_path=__init__file_path, ) test_1_abs_path = add_test("test_1_") list_of_executable_files = get_executable_files_in_folder(test_1_abs_path) D(f"list_of_executable_files = {list_of_executable_files}") D(f"kwargs:\n\t{kwargs}") variant_id = get_variant_id(kwargs) D(f"kwargs:\n\t{kwargs}") if variant_id == 1 : # "build only the FIRST executable file" kwargs['cmd'][2] = list_of_executable_files[0] self.window.run_command("exec", kwargs) else: # default, execute ALL self.execute_each_file(list_of_executable_files, kwargs) # D("THIS IS AFTER EXEC COMMAND") # self.window.run_command("exec", kwargs) # add_test("test_2_") # add_test("test_3_") def execute_each_file(self, list_of_executable_files, kwargs): def async_recursive(i): if i >= len(list_of_executable_files): return # Execute file 'i' kwargs['cmd'][2] = list_of_executable_files[i] self.window.run_command("exec", kwargs) wait_time = (i+1)*1000 D(f"wait_time = {wait_time}") # Schedule the next iteration sublime.set_timeout_async(lambda: async_recursive(i+1), wait_time) async_recursive(i=0)def get_variant_id(kwargs): if 'variant_id' in kwargs.keys(): variant_id = int(kwargs.get('variant_id')) del kwargs['variant_id'] else: variant_id = 0 D(f"variant_id:\n\t{variant_id}") return variant_iddef get_current_pc(): global CURRENT_PC if CURRENT_PC is not None: return CURRENT_PC else: global FOLDER_TO_SAVE_TEST_SUBFOLDERS global TEMPLATE_TEST_FOLDERS folder_to_save_was_found = False template_folder_was_found = False output_PC = None for PC, folder_to_save in FOLDER_TO_SAVE_TEST_SUBFOLDERS.items(): D(f"PC = {PC} : folder_to_save = {folder_to_save}") if does_path_exists(folder_to_save): folder_to_save_was_found = True if PC in TEMPLATE_TEST_FOLDERS.keys(): template_folder = TEMPLATE_TEST_FOLDERS[PC] if does_path_exists(template_folder): CURRENT_PC = PC return CURRENT_PC for PC, template_folder in TEMPLATE_TEST_FOLDERS.items(): D(f"PC = {PC} : template_folder = {template_folder}") if does_path_exists(folder_to_save): template_folder_was_found = True if folder_to_save_was_found==False and template_folder_was_found==False: err_msg = f"NONE OF THESE FOLDERS WAS FOUND:\n" err_msg += f"TEMPLATE_TEST_FOLDERS:\n{TEMPLATE_TEST_FOLDERS}" err_msg += f"\n\nALSO, NONE OF THESE FOLDERS WAS FOUND:\n" err_msg += f"FOLDER_TO_SAVE_TEST_SUBFOLDERS:\n{FOLDER_TO_SAVE_TEST_SUBFOLDERS}" elif folder_to_save_was_found==True and template_folder_was_found==False: err_msg = f"NONE OF THESE FOLDERS WAS FOUND:\n{TEMPLATE_TEST_FOLDERS}" elif folder_to_save_was_found==False and template_folder_was_found==True: err_msg = f"NONE OF THESE FOLDERS WAS FOUND:\n{FOLDER_TO_SAVE_TEST_SUBFOLDERS}" elif folder_to_save_was_found==True and template_folder_was_found==True: err_msg = f"I think there is an error on the following definitions:" err_msg += f"\n\nTEMPLATE_TEST_FOLDERS:\n{TEMPLATE_TEST_FOLDERS}" err_msg += f"\n\nFOLDER_TO_SAVE_TEST_SUBFOLDERS:\n{FOLDER_TO_SAVE_TEST_SUBFOLDERS}" err_msg += f">>> Please add/correct it by changing this file:\n{__file__}" sublime.message_dialog(err_msg) raise ValueError(err_msg)def assert_correct_file_name(file_abs_path): global ALLOWED_FILE_NAMES # D(f"file_abs_path = {file_abs_path}") # D(f"get_file_name_without_suffix(file_abs_path) = {get_file_name_without_suffix(file_abs_path)}") if get_file_name_without_suffix(file_abs_path) not in ALLOWED_FILE_NAMES: raise_not_correct_file(ALLOWED_FILE_NAMES[0])def create_new_Test_folder(): D(f"Entering: create_new_Test_folder") global FOLDER_TO_SAVE_TEST_SUBFOLDERS current_PC = get_current_pc() destination_path = FOLDER_TO_SAVE_TEST_SUBFOLDERS[current_PC] all_save_folders = os.listdir(destination_path) last_saved_folder_number = 0 for folder_name in all_save_folders: if does_string_starts_with(folder_name, "Test_"): test_number = int(get_numeric_chars(folder_name)) # D(f"test_number = {test_number}") if test_number > last_saved_folder_number: last_saved_folder_number = test_number new_folder_name = "Test_" + str(last_saved_folder_number + 1) D(f"new_folder_name = {new_folder_name}") new_Test_folder_abs_path = destination_path+"\\"+new_folder_name D(f"new_Test_folder_abs_path = {new_Test_folder_abs_path}") assert not does_path_exists(abs_path) # if not DEBUG: os.mkdir(new_Test_folder_abs_path) return new_Test_folder_abs_pathdef is_executable_file(file_name): global EXECUTABLE_FILE_EXTENSIONS global EXCLUDE_THESE_EXECUTABLE_FILES file_Path = pathlib.Path(file_name) # D(f"file_Path = {file_Path}") D(f"file_Path.name = {file_Path.name}") # D(f"file_Path.suffix = {file_Path.suffix}") if file_Path.name in EXCLUDE_THESE_EXECUTABLE_FILES: return False for extension in EXECUTABLE_FILE_EXTENSIONS: if file_Path.suffix == extension: return True return Falsedef get_executable_files_in_folder(abs_folder_path): items = get_list_of_all_files_in_folder_and_subfolders(abs_folder_path) # D(f"items = {items}") files = filter(lambda x: os.path.isfile(x), items) # D(f"files = {files}") executable_files = filter(lambda x: is_executable_file(x), files) # D(f"executable_files = {executable_files}") return list(executable_files)def does_string_starts_with(str_, word): if str_[:len(word)] == word: return True else: return Falsedef does_string_ends_with(str_, word): if str_[-len(word):] == word: return True else: return Falsedef get_numeric_chars(input_str): return ''.join([char for char in input_str if char.isdigit()])def add_modified_subtest_folder_to_folder( destination_test_folder, subtest_folder_name, new__init__file_path): global FOLDER_TO_SAVE_TEST_SUBFOLDERS global TEMPLATE_TEST_FOLDERS current_PC = get_current_pc() list_template_folders = list(os.listdir(TEMPLATE_TEST_FOLDERS[current_PC])) if not subtest_folder_name in list_template_folders: raise_A_not_found_in_list(A=subtest_folder_name, list_=list_template_folders) source_path = TEMPLATE_TEST_FOLDERS[current_PC]+"\\"+subtest_folder_name destination_path = destination_test_folder+"\\"+subtest_folder_name # if not DEBUG: copy_folder_or_file(source_path, destination_path) replace_all__init__files_in_folder_with_the_current_one(destination_path, new__init__file_path) return destination_pathdef replace_all__init__files_in_folder_with_the_current_one(folder, new__init__file_path): all_sub_paths = get_list_of_all_files_in_folder_and_subfolders(folder) D(f"all_sub_paths:\n\t{all_sub_paths}") old__init__paths = filter( lambda str_: does_string_ends_with(str_, "__init__.py"), all_sub_paths ) for old__init__file_path in old__init__paths: D(f"old__init__file = {old__init__file_path}") os.remove(old__init__file_path) copy_folder_or_file(source_path=new__init__file_path, destination_path=old__init__file_path)def get_list_of_all_files_in_folder_and_subfolders(starting_path): def recursive_function(starting_path, list_=list()): list_.append(starting_path) if os.path.isdir(starting_path): for item in os.listdir(starting_path): abs_path = starting_path+"\\"+item recursive_function(abs_path, list_) output_list = list() recursive_function(starting_path, output_list) return output_listdef copy_folder_or_file(source_path, destination_path): if os.path.isdir(source_path): shutil.copytree(source_path, destination_path) if os.path.isfile(source_path): shutil.copyfile(source_path, destination_path)def change_kwargs_cmd_python_interpreter(python_interpreter, **kwargs): old_cmd = kwargs['cmd'] new_cmd = [python_interpreter] + old_cmd[1:] kwargs['cmd'] = new_cmd # if DEBUG: print(f">>> new_cmd = {new_cmd}") # kwargs['working_dir'] = "" # if DEBUG: print(f">>> kwargs['working_dir'] = {kwargs['working_dir']}") return kwargsdef find_python_interpreter(**kwargs): global FILE2INTERPRETER_DICT if FILE2INTERPRETER_DICT is None: FILE2INTERPRETER_DICT = load_file2interpreter_dictionary() # if DEBUG: print(f">>> FILE2INTERPRETER_DICT:\n\t{FILE2INTERPRETER_DICT}") file_abs_path = kwargs['cmd'][2] # if DEBUG: print(f">>> file_abs_path = {file_abs_path}") if not does_path_exists(file_abs_path): raise_file_path_does_not_exists(file_abs_path) pipenv_venv = get_pipenv_of_file(file_abs_path) # if DEBUG: print(f">>> pipenv_venv = {pipenv_venv}") python_interpreter = pipenv_venv + "\\Scripts\\python.exe" # file_name = pathlib.Path(__file__).stem # if DEBUG: print(f">>> file_name = {file_name}") # if DEBUG: print(f">>> kwargs = {kwargs}") return python_interpreterdef does_var_exist(variable_name: str) -> bool: if variable_name in locals(): return True if variable_name in globals(): return Truedef one_time_operation(func): #UNUSED def wrap(*args, **kwargs): global_var_name = "was_function_" + func.__name__ + "_performed" if not does_var_exist(global_var_name): globals()[global_var_name] = False elif globals()[global_var_name] == True: return # if DEBUG: print(f"{global_var_name} = {globals()[global_var_name]}") # if DEBUG: print(func.__name__) result = func(*args, **kwargs) globals()[global_var_name] = True return result return wrapdef does_path_exists(abs_path): return os.path.exists(abs_path)def get_folder_of_file(abs_path): if os.path.isdir(abs_path): return abs_path folder = os.path.dirname(abs_path) return folderdef get_path_without_suffix(path): abs_path = pathlib.PurePosixPath(path) suffixes = abs_path.suffixes if DEBUG: print(f">>> suffixes = {suffixes}") tot_len = 0 for s in suffixes: tot_len += len(s) abs_path = str(abs_path) path_without_suffix = abs_path[:-tot_len] return path_without_suffixdef get_file_name_without_suffix(path): return pathlib.Path(path).stemdef is_a_subfolder_of_b(a:str, b:str): if a == b[:len(a)]: return True else: return Falsedef get_abs_path_for_pickled_dict(): # if DEBUG: print(f"__file__ = {__file__}") path_without_suffix = get_path_without_suffix(__file__) # if DEBUG: print(f"path_without_suffix = {path_without_suffix}") abs_path = path_without_suffix+'_file2interpreter_dict'+'.pkl' if DEBUG: print(f">>> abs_path = {abs_path}") return abs_pathdef save_file2interpreter_dictionary(): global FILE2INTERPRETER_DICT if FILE2INTERPRETER_DICT is None: FILE2INTERPRETER_DICT = load_file2interpreter_dictionary() abs_path = get_abs_path_for_pickled_dict() with open(abs_path, 'wb') as f: pickle.dump(FILE2INTERPRETER_DICT, f)def load_file2interpreter_dictionary(): abs_path = get_abs_path_for_pickled_dict() with open(abs_path, 'rb') as f: file2interpreter_dict = pickle.load(f) return file2interpreter_dictdef add_entry_to_file2interpreter_dictionary(file_path, pipenv_venv): global FILE2INTERPRETER_DICT if FILE2INTERPRETER_DICT is None: FILE2INTERPRETER_DICT = load_file2interpreter_dictionary() if DEBUG: print(f"file_path = {file_path}") if DEBUG: print(f"pipenv_venv = {pipenv_venv}") assert os.path.isfile(file_path) assert os.path.isdir(pipenv_venv) assert os.path.exists(file_path) assert os.path.exists(pipenv_venv) FILE2INTERPRETER_DICT[file_path] = pipenv_venv save_file2interpreter_dictionary()def subprocess_run_command(cmd): sub_output = subprocess.run( cmd, capture_output=True, universal_newlines=True, text=True, shell=True, encoding = "utf-8" ) output = sub_output.stdout + sub_output.stderr # if DEBUG: print(f"output.strip() = \n{output.strip()}") return outputdef get_pipenv_of_file(file_path): global FILE2INTERPRETER_DICT if FILE2INTERPRETER_DICT is None: FILE2INTERPRETER_DICT = load_file2interpreter_dictionary() # if DEBUG: (f">>> FILE2INTERPRETER_DICT:\n\t{FILE2INTERPRETER_DICT}") for key_file_path, pipenv_venv in FILE2INTERPRETER_DICT.items(): # if DEBUG: print(f">>> key_file_path = {key_file_path}") # if DEBUG: print(f">>> pipenv_venv = {pipenv_venv}") if is_a_subfolder_of_b(a=file_path, b=key_file_path): # if DEBUG: print(f">>>\tfile_path:\n\t'{file_path}'\n\tis in key:\n\t'{key_file_path}'") return pipenv_venv pipenv_venv = subprocess_check_which_venv(file_path) return pipenv_venvdef subprocess_check_which_venv(file_path): folder_path = get_folder_of_file(file_path) if DEBUG: print(f"folder_path = {folder_path}") cmd_1 = f"cd {folder_path}" cmd_2 = f"pipenv --venv" output = subprocess_run_command(cmd_1+" && "+cmd_2).replace("\n", "") # if DEBUG: print(f"output = {output}") initial_err_msg = "No virtualenv has been created for this project" final_err_msg = "yet!Aborted!" if output[:len(initial_err_msg)] == initial_err_msg and output[-len(final_err_msg):] == final_err_msg: # if DEBUG: print("ERRORS FOUND") raise_file_path_does_not_have_a_pipenv_folder(file_path) return None else: # if DEBUG: print("no error found") add_entry_to_file2interpreter_dictionary(file_path, pipenv_venv:=output) return pipenv_venvdef raise_file_path_does_not_have_a_pipenv_folder(file_path): err_msg = f"\nFile:\n'{file_path}'\nIS NOT INSIDE A 'pipenv folder'!\n" err_msg += f" 1. Please choose a folder that defines this project.\n" err_msg += f" 2. Using cmd promt 'cd' to said folder.\n" err_msg += f" 3. Then use the command 'pipenv shell' to create a 'pipenv folder'." sublime.message_dialog(err_msg) raise ValueError(err_msg)def raise_file_path_does_not_exists(file_path): err_msg = f"File:\n'{file_path}'\nDOES NOT EXIST!\n" sublime.message_dialog(err_msg) raise ValueError(err_msg)def raise_not_correct_file(file_name): err_msg = f"File name should be:\n'{file_name}'\n" err_msg += f"PLEASE CHANGE BUILD, OR GO TO THE CORRECT FILE\n" sublime.message_dialog(err_msg) raise ValueError(err_msg)def raise_A_not_found_in_list(A, list_): err_msg = f"ELEMENT {A} SHOULD HAVE BEEN FOUND IN LIST:'\n" err_msg += f"{list_}\n" sublime.message_dialog(err_msg) raise ValueError(err_msg)