Source code for pySIMsalabim.install.get_SIMsalabim

import sys, os, subprocess, shutil, json, requests, zipfile, io
from packaging import version
from pathlib import Path
from getpass import getpass

######### Parameter Definitions ###################################################################
cwd = Path.cwd()
folder_name = 'kostergroup-SIMsalabim-'
min_fpc_version = '3.2.0'

######### Function Definitions ####################################################################
[docs] def cmd_yes_no_question(question, default = "yes"): """_summary_ Parameters ---------- question : str question to ask the user default : str, optional default answer, by default "yes" Returns ------- bool whether the default answer is valid or not Raises ------ ValueError If the default answer is not valid """ # valid answers (yes/no) valid = {'yes' : True, 'y': True, 'ye': True, 'no': False, 'n': False} # Set the default answer. if default is None: prompt = " [y/n] " elif default == 'yes': prompt = " [Y/n] " elif default == 'no': prompt = " [y/N] " else: raise ValueError(f"Invalid default answer: {default}\n") while True: # Capture user input sys.stdout.write(question + prompt) choice = input() # convert the input to lowercase choice = choice.lower() if default is not None and choice == "": # Use default value return valid[default] elif choice in valid: # Use user input return valid[choice] else: # Incorrect input sys.stdout.write('Please respond with "y" or "n"\n')
[docs] def clear_current_working_directory(cwd, folder_name='kostergroup-SIMsalabim-'): """_summary_ Parameters ---------- cwd : string Current working directory folder_name : string, optional Name of the folder to download, by default 'kostergroup-SIMsalabim-' Returns ------- bool Whether the folder was removed or not """ # Clear the current working directory for dirpath, dirnames, files in os.walk(cwd): for dirname in dirnames: if dirname.startswith(folder_name): result = cmd_yes_no_question(f"Are you sure you want to overwrite the {dirname} folder?") if result == True: shutil.rmtree(os.path.join(cwd,dirname)) print(f"Found and removed a folder named {dirname}") return True elif result is False: print(f"Not allowed to write into folder {dirname}") return False else: # print(f"No folder found named SIMsalabim, continue.") return True
[docs] def get_SIMsalabim_source(cwd, folder_name='kostergroup-SIMsalabim-',verbose=False): """ Get the latest release from the Kostergroup Github Parameters ---------- cwd : string Current working directory folder_name : string, optional Name of the folder to download, by default 'kostergroup-SIMsalabim-' verbose : bool, optional Print verbose output, by default False Returns ------- int 0 : Success 2 : Failed 3 : Failed """ if verbose: print("Getting the latest release from the Kostergroup Github") # Get the SIMsalabim source code. if os.path.exists(os.path.join(cwd, 'SIMsalabim')): # Pop out dialog box to confirm overwriting result = cmd_yes_no_question("Are you sure you want to overwrite the 'SIMsalabim' folder?") if result == True: # Remove folder shutil.rmtree(os.path.join(cwd, 'SIMsalabim')) # # Get the files from the latest release url = 'https://api.github.com/repos/kostergroup/SIMsalabim/zipball' response = requests.get(url) # Open the zip file z = zipfile.ZipFile(io.BytesIO(response.content)) # Extract all the files z.extractall(path=cwd) for dirpath, dirnames, files in os.walk(cwd): for dirname in dirnames: if dirname.startswith(folder_name): # Rename folder shutil.move(os.path.join(cwd, dirname), os.path.join(cwd, 'SIMsalabim')) print("\nGot the latest release of SIMsalabim") return 0 else: print('We keep the current SIMsalabim version') return 0 else: # # Get the files from the latest release url = 'https://api.github.com/repos/kostergroup/SIMsalabim/zipball' response = requests.get(url) # Open the zip file z = zipfile.ZipFile(io.BytesIO(response.content)) # Extract all the files z.extractall(path=cwd) for dirpath, dirnames, files in os.walk(cwd): for dirname in dirnames: if dirname.startswith(folder_name): # print(f"Found a folder named {dirname}") # Rename folder shutil.move(os.path.join(cwd, dirname), os.path.join(cwd, 'SIMsalabim')) print("\nGot the latest release of SIMsalabim") return 0
[docs] def get_SIMsalabim_assets(cwd,folder_name='kostergroup-SIMsalabim-',verbose=False): """ Get the latest compiled binaries from the Kostergroup Github Parameters ---------- cwd : string Current working directory folder_name : string, optional Name of the folder to download, by default 'kostergroup-SIMsalabim-' verbose : bool, optional Print verbose output, by default False Returns ------- int 0 : Success 1 : Success 2 : Failed 3 : Failed """ if verbose: print("Getting the latest compiled binaries from the Kostergroup Github") # Get the assets from the latest release url = "https://api.github.com/repos/kostergroup/SIMsalabim/releases/latest" response = requests.get(url) data = json.loads(response.text) for asset in data["assets"]: download_url = asset["browser_download_url"] filename = asset["name"] response = requests.get(download_url) open(os.path.join(cwd,filename), "wb").write(response.content) for dirpath, dirnames, files in os.walk(cwd): for filename in files: if filename.startswith('simss') and os.path.exists(os.path.join(cwd, filename)): print(f"Found a folder named {filename}") # Rename folder shutil.move(os.path.join(cwd, filename), os.path.join(cwd, 'SIMsalabim','SimSS',filename)) elif filename.startswith('zimt') and os.path.exists(os.path.join(cwd, filename)): print(f"Found a folder named {filename}") # Rename folder shutil.move(os.path.join(cwd, filename), os.path.join(cwd, 'SIMsalabim','ZimT',filename)) else: pass return 1
[docs] def use_SIMsalabim_source(cwd, folder_name='kostergroup-SIMsalabim-'): """ Use the SIMsalabim source code Parameters ---------- cwd : string Current working directory folder_name : string, optional Name of the folder to download, by default 'kostergroup-SIMsalabim-' Returns ------- int 0 : Success 2 : Failed 3 : Failed """ # Clear the working directory. TEMP disabled # result = clear_current_working_directory(cwd, folder_name) result = True if result == True: result_get = get_SIMsalabim_source(cwd, folder_name) return result_get elif result == False: print('Script terminated manually') return 3 else: print('Failed') return 2
[docs] def install_SIMsalabim(cwd, folder_name='kostergroup-SIMsalabim-',verbose=False): """Install SIMsalabim in the current working directory Parameters ---------- cwd : string Current working directory folder_name : string, optional Name of the folder to download, by default 'kostergroup-SIMsalabim-' verbose : bool, optional Print verbose output, by default False Returns ------- int 0 : Success 1 : Success 2 : Failed 3 : Failed """ # Check if fpc installed if verbose: print("Checking for Free Pascal Compiler (fpc) package") if shutil.which("fpc") is not None: # fpc is installed, check the version and print to stdout. result = subprocess.run(["fpc", "-iV"], stdout=subprocess.PIPE, text=True) fpc_version = result.stdout # remove possible newline character if '\n' in fpc_version: fpc_version = fpc_version.strip('\n') # fpc version must be larger than min_fpc_version if version.parse(fpc_version) > version.parse(min_fpc_version): if verbose: print(f'Free Pascal Compiler (fpc) is installed with version >= {min_fpc_version}\n') result_fpc = use_SIMsalabim_source(cwd, folder_name) # sys.exit(result_fpc) # Compile the programs # compile simss with fpc in os.path.join(path2prog,'SimSS') os.chdir(os.path.join(cwd,'SIMsalabim','SimSS')) os.system('fpc simss.pas') os.chdir(cwd) # compile zimt with fpc in os.path.join(path2prog,'ZimT') cwd = os.getcwd() # Get current working directory os.chdir(os.path.join(cwd,'SIMsalabim','ZimT')) os.system('fpc zimt.pas') os.chdir(cwd) if verbose: print('SIMsalabim programs have been compiled successfully!') else: # fpc version requirement not met print(f'Installed Free Pascal Compiler (fpc) version is {fpc_version}, but must be at least 3.2.0\n') result = cmd_yes_no_question("Do you want to continue with the pre-compiled binaries (y) or abort and update the Free Pascal Compiler (n) (recommended)", 'no') if result is True: # download assets print("\ndownload assets") result_assets = get_SIMsalabim_assets(cwd, verbose) sys.exit(result_assets) elif result is False: # return and exit sys.exit(3) else: # fpc is not installed. print("Free Pascal Compiler is not installed.\n") result = cmd_yes_no_question("Do you want to continue with the pre-compiled binaries (y) or abort and install the Free Pascal Compiler (n) (recommended)", 'no') if result is True: # download assets print("\ndownload assets") result_assets = get_SIMsalabim_assets(cwd, verbose) sys.exit(result_assets) elif result is False: # return and exit sys.exit(3)
[docs] def install_fpc_Linux(): """ Install Free Pascal Compiler on Linux """ # check if system is Linux if os.name != 'posix': print('This function is only available on Linux systems') sys.exit() # check if apt-get is available if shutil.which("apt-get") is None: print('apt-get is not available on this system') sys.exit() # Install Free Pascal Compiler password = getpass('Sudo password:') # run the command sudo apt-get install fp-compiler and enter the password and print the output os.system('echo {} | sudo -S apt-get install fp-compiler'.format(password))
# def install_parallel_Linux(): # """ Install GNU Parallel on Linux # """ # # check if system is Linux # if os.name != 'posix': # print('This function is only available on Linux systems') # sys.exit() # # check if apt-get is available # if shutil.which("apt-get") is None: # print('apt-get is not available on this system') # sys.exit() # # Install GNU Parallel # password = getpass('Sudo password:') # # run the command sudo apt-get install parallel and enter the password and print the output # os.system('echo {} | sudo -S apt-get install parallel'.format(password)) # def fpc_prog(cwd,prog_name): # """_summary_ # Parameters # ---------- # cwd : string # Current working directory # prog_name : string # Name of the program to compile # """ # # Check if fpc installed # if verbose: # print("Checking for Free Pascal Compiler (fpc) package") # if shutil.which("fpc") is not None: # # fpc is installed, check the version and print to stdout. # result = subprocess.run(["fpc", "-iV"], stdout=subprocess.PIPE, text=True) # fpc_version = result.stdout # # remove possible newline character # if '\n' in fpc_version: # fpc_version = fpc_version.strip('\n') # # fpc version must be larger than min_fpc_version # if version.parse(fpc_version) > version.parse(min_fpc_version): # if verbose: # print(f'Free Pascal Compiler (fpc) is installed with version >= {min_fpc_version}\n') # # Compile the programs # os.chdir(os.path.join(cwd,prog_name)) # os.system(f'fpc {prog_name}.pas') # os.chdir(cwd) # else: # # fpc version requirement not met # print(f'Installed Free Pascal Compiler (fpc) version is {fpc_version}, but must be at least 3.2.0\n') # result = cmd_yes_no_question("Do you want to continue with the pre-compiled binaries (y) or abort and update the Free Pascal Compiler (n) (recommended)", 'no') # if result is True: # # download assets # print("\ndownload assets") # result_assets = get_SIMsalabim_assets(cwd, verbose) # sys.exit(result_assets) # elif result is False: # # return and exit # sys.exit(3) # else: # # fpc is not installed. # print("Free Pascal Compiler is not installed.\n") # sys.exit(3)
[docs] def fpc_prog(cwd,prog_name,show_term_output=True,force_fpc=True,verbose=True): """Compile program using fpc Parameters ---------- cwd : string String of the absolute path to the program prog_name : string Name of the program to compile show_term_output : bool, optional show terminal output from the compilation, by default True force_fpc : bool, optional force recompile with fpc even if compiled program already exists, by default True verbose : bool, optional print output of the compilation, by default True """ is_windows = (os.name == 'nt') # Check if we are on Windows cwd = str(cwd) # Convert to string # check if compiled = False while not compiled: if shutil.which("fpc") is not None: # fpc is installed, check the version and print to stdout. result = subprocess.run(["fpc", "-iV"], stdout=subprocess.PIPE, text=True) fpc_version = result.stdout # remove possible newline character if '\n' in fpc_version: fpc_version = fpc_version.strip('\n') # fpc version must be larger than min_fpc_version if version.parse(fpc_version) >= version.parse(min_fpc_version): if verbose: print(f'Free Pascal Compiler (fpc) is installed with version >= {min_fpc_version}\n') # Check if the program is already compiled if (os.path.isfile(os.path.join(cwd,prog_name+'.exe')) and is_windows) or (os.path.isfile(os.path.join(cwd,prog_name)) and not is_windows): if force_fpc: if show_term_output == True: output_direct = None else: output_direct = subprocess.DEVNULL try: subprocess.check_call(['fpc', prog_name.lower()+'.pas'], encoding='utf8', stdout=output_direct, cwd=cwd, shell=is_windows) except subprocess.CalledProcessError: print('Error compiling '+prog_name+' in '+cwd) raise ChildProcessError if verbose: print('\n'+prog_name+' already existed but was recompiled'+'\n') else: if verbose: print('\n'+prog_name+' already compiled') else: # Compile the program if show_term_output == True: output_direct = None else: output_direct = subprocess.DEVNULL try: subprocess.check_call(['fpc', prog_name.lower()+'.pas'], encoding='utf8', stdout=output_direct, cwd=cwd, shell=is_windows) if verbose: print('\n'+prog_name+' was not compiled so we did it!'+'\n') except subprocess.CalledProcessError: print('Error compiling '+prog_name+' in '+cwd) raise ChildProcessError compiled = True else: # fpc version requirement not met print(f'Installed Free Pascal Compiler (fpc) version is {fpc_version}, but must be at least 3.2.0\n') print('Please update the Free Pascal Compiler to the latest version') sys.exit(3) else: # fpc is not installed. print("Free Pascal Compiler is not installed.\n") result = cmd_yes_no_question("Do you want to continue and install the Free Pascal Compiler (only works on Linux) (y) or abort (n) (recommended)", 'no') if result is True: # install fpc install_fpc_Linux() # sys.exit(0) elif result is False: # return and exit sys.exit(3)
######### Script ################################################################################## if __name__ == "__main__": install_SIMsalabim(cwd,verbose=True) sys.exit(0)