diff --git a/README.md b/README.md index 19d0d3f5691a0120876d68f5fa0a2beefee77efb..25c4f8b4ac1e84a8e3335c212a51c499d8abb3dc 100755 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The Quingo installation comprises of two main steps: ### Install the Runtime system and simulator Install Quingo runtime system with required simulators using the following command: ```sh -git clone https://gitee.com/hpcl_quanta/quingo-runtime.git +git clone https://gitee.com/quingo/quingo-runtime.git cd /your/download/path/quingo-runtime/ pip install -e . ``` @@ -72,4 +72,4 @@ The `Quingo_interface` class expose the following methods: - For QCIS-based backend, the result format is defined by PyQCISim. Please refer to the docstring of `quingo.if_backend.non_arch_backend.pyqcisim_quantumsim.PyQCISim_quantumsim::execute()` ## Quingo programming tutorial -At present, Qingguo runtime system has included sample programs such as `Bell_state`, `GHZ`, `VQE`, etc. Details can be found [here](https://gitee.com/hpcl_quanta/quingo-runtime/tree/master/src/examples). \ No newline at end of file +At present, Qingguo runtime system has included sample programs such as `Bell_state`, `GHZ`, `VQE`, etc. Details can be found [here](https://gitee.com/quingo/quingo-runtime/tree/master/src/examples). \ No newline at end of file diff --git a/README_ZH.md b/README_ZH.md index 27afb410b12f022db7298f6324a881afefae9418..955697dc26425216d0fc9043abc5e3c9023d5984 100755 --- a/README_ZH.md +++ b/README_ZH.md @@ -10,7 +10,7 @@ 依次执行以下命令便可以安装青果运行时系统、PyQCAS模拟器以及PyQCISim模拟器。 ```sh -git clone https://gitee.com/hpcl_quanta/quingo-runtime.git +git clone https://gitee.com/quingo/quingo-runtime.git cd /your/download/path/quingo-runtime/ pip install -e . ``` @@ -71,4 +71,4 @@ The result of bell_state is: - 对于能够执行QCIS指令的后端,结果的格式由PyQCISim进行定义。详情请参考`quingo.if_backend.non_arch_backend.pyqcisim_quantumsim.PyQCISim_quantumsim::execute()`中的文档描述。 ## 青果示例程序 -目前青果运行时系统中已经包含了`Bell_state`、`GHZ`、`VQE`等示例程序,详情可见[此处](https://gitee.com/hpcl_quanta/quingo-runtime/tree/master/src/examples)。 \ No newline at end of file +目前青果运行时系统中已经包含了`Bell_state`、`GHZ`、`VQE`等示例程序,详情可见[此处](https://gitee.com/quingo/quingo-runtime/tree/master/src/examples)。 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 7b48b3029a7ce8584b9bb0975e90162e36f27d0c..639f349d98249751e85b74d313c7cb048c02b409 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,15 +1,15 @@ [metadata] name = quingo -version = 0.1.3 +version = 0.1.4 author = Xiang Fu author_email = gtaifu@gmail.com use_2to3 = False description = Quingo Runtime System long_description = file: README.md long_description_content_type = text/markdown -url = https://gitee.com/hpcl_quanta/quingo-runtime +url = https://gitee.com/quingo/quingo-runtime project_urls = - Bug Tracker = https://gitee.com/hpcl_quanta/quingo-runtime/issues + Bug Tracker = https://gitee.com/quingo/quingo-runtime/issues classifiers = Programming Language :: Python :: 3 :: Only License :: OSI Approved :: Apache Software License @@ -27,6 +27,7 @@ install_requires = colorama termcolor requests + tqdm [options.packages.find] where = src \ No newline at end of file diff --git a/setup.py b/setup.py index 65db3032d27270ce5301e86e76325019a586554b..b908cbe55cb344569d32de1dfc10ca7323828dc5 100755 --- a/setup.py +++ b/setup.py @@ -1,193 +1,3 @@ -import requests -import json -import distutils.spawn -import subprocess -import platform -import zipfile -import shutil -import tempfile -from pathlib import Path -from setuptools import setup -from setuptools.command.develop import develop -from setuptools.command.install import install +import setuptools - -def set_path_env_on_Linux(install_path): - """Set path environment to contain the milr quingo compiler on Linux. - """ - quingoc_dir = install_path / 'bin' - - ret_value = subprocess.run("echo $PATH", stdout=subprocess.PIPE, - stderr=subprocess.PIPE, text=True, shell=True) - - if ret_value.returncode != 0: - raise RuntimeError("Failed to retrieve system path using 'echo $PATH'.") - - if str(quingoc_dir.absolute()) in ret_value.stdout: - return - - bash_profile = Path.home() / '.bash_profile' - bashrc = Path.home() / '.bashrc' - shell_cmd = "if [ -f \"{bashrc_path}\" ]\nthen\n \ - echo 'export PATH={quingoc_dir_path}:$PATH' >> {bashrc_path}\n \ - elif [ -f \"{bash_profile_path}\" ]\nthen\n \ - echo 'export PATH={quingoc_dir_path}:$PATH' >> {bash_profile_path}\n \ - fi\n" - set_env_cmd = shell_cmd.format( - bashrc_path=bashrc, bash_profile_path=bash_profile, quingoc_dir_path=quingoc_dir) - - ret_value = subprocess.run(set_env_cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, text=True, shell=True) - - if(ret_value.returncode != 0): - raise RuntimeError("Failed add \"{}\" to path environment with the" - "following error: {}".format(quingoc_dir, ret_value.stderr)) - - print("Installed mlir quingo compiler at directory:{}".format(quingoc_dir)) - - -def install_on_Linux(mlir_compiler_path): - """Install quingo compiler on Linux. - """ - mlir_compiler_path.chmod(0o744) - quingoc_install_dir = Path.home() / '.local' - - mlir_compiler_install_cmd = '"{}" --prefix="{}" --exclude-subdir'.format( - mlir_compiler_path, quingoc_install_dir) - - print("mlir_compiler_install_cmd: ", mlir_compiler_install_cmd) - - ret_value = subprocess.run(mlir_compiler_install_cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, text=True, shell=True) - if(ret_value.returncode != 0): - raise RuntimeError("Failed to install lastest quingo compiler with the" - "following error: {}".format(ret_value.stderr)) - - set_path_env_on_Linux(quingoc_install_dir) - - -def set_path_on_Windows(install_path): - """Set path environment to contain the milr quingo compiler on Windows. - """ - # Nothing to do, quingo-runtime will search the default install path - # Default path is Path.home() / '.quingo' - - return - - -def install_on_Windows(mlir_compiler_path): - """Install quingo compiler on Windows. - """ - - mlir_compiler_install_path = Path.home() / '.quingo' - - zip_file = zipfile.ZipFile(mlir_compiler_path) - zip_list = zip_file.namelist() - zip_file.extractall(mlir_compiler_install_path) - zip_file.close() - - files = [file for file in mlir_compiler_install_path.glob("*/*") if file.is_file()] - for file in files: - file.replace(mlir_compiler_install_path / file.name) - - set_path_on_Windows(mlir_compiler_install_path) - - -def install_compiler(os_name, mlir_compiler_path): - assert os_name in ['Linux', 'Windows'] - if(os_name == 'Windows'): - install_on_Windows(mlir_compiler_path) - if(os_name == 'Linux'): - install_on_Linux(mlir_compiler_path) - - -def download_compiler(os_name, tmp_dir_name): - assert os_name in ['Linux', 'Windows'] - os_dl_suffix = { - 'Linux': '.sh', - 'Windows': '.zip' - } - dl_file_suffix = os_dl_suffix[os_name] - - latest_release_url = "https://gitee.com/api/v5/repos/{owner}/{repo}/releases/latest".format( - owner="hpcl_quanta", repo="quingo-runtime") - - try: - latest_release = requests.get(latest_release_url).text - release_info = json.loads(latest_release) - assets = release_info['assets'] - quingoc_asset = None - for asset in assets: - if 'name' in asset and asset['name'].endswith(dl_file_suffix): - quingoc_asset = asset - break - if quingoc_asset is None: - raise RuntimeError("Failed to download quingo compiler from gitee.") - - quingoc_url = quingoc_asset['browser_download_url'] + '/' + quingoc_asset['name'] - quingoc_response = requests.get(quingoc_url) - - mlir_compiler_path = tmp_dir_name / quingoc_asset['name'] - with mlir_compiler_path.open('wb') as tmp_dl_file: - num_bytes = tmp_dl_file.write(quingoc_response.content) - print("installation file has been downloaded to tmp file {} ({} bytes). ".format( - mlir_compiler_path, num_bytes)) - return mlir_compiler_path - - except Exception as e: - raise RuntimeError("Failed to parse information retrieved from gitee with the " - "following error: {}".format(e)) - - -def download_and_install_latest_quingoc(): - """Download the latest mlir quingo compiler. - """ - os_name = platform.system() - if os_name not in ['Linux', 'Windows']: - raise SystemError("Currently pip installation does not support {}".format(os_name)) - - tmp_dir = tempfile.TemporaryDirectory() - tmp_dir_path = Path(tmp_dir.name) - - mlir_compiler_path = download_compiler(os_name, tmp_dir_path) - install_compiler(os_name, mlir_compiler_path) - - shutil.rmtree(tmp_dir_path) - - -def friendly(command_subclass): - """A decorator for classes subclassing one of the setuptools commands. - - It modifies the run() method so that it prints a friendly greeting. - """ - orig_run = command_subclass.run - - def modified_run(self): - default_path = Path.home() / '.quingo' - quingoc_path = distutils.spawn.find_executable('quingoc', str(default_path)) - - if quingoc_path is None: - quingoc_path = distutils.spawn.find_executable('quingoc') - - if quingoc_path is None: - download_and_install_latest_quingoc() - - orig_run(self) - - command_subclass.run = modified_run - return command_subclass - - -@friendly -class CustomDevelopCommand(develop): - pass - - -@friendly -class CustomInstallCommand(install): - pass - - -setup(cmdclass={ - 'install': CustomInstallCommand, - 'develop': CustomDevelopCommand, }) +setuptools.setup() diff --git a/src/quingo/core/compiler_config.py b/src/quingo/core/compiler_config.py index f0a66d807b63568a198bea81fdeb40ffd7f5e87a..f670c52c96039f43ec6d1cebc4a425777ed2ee4e 100644 --- a/src/quingo/core/compiler_config.py +++ b/src/quingo/core/compiler_config.py @@ -32,7 +32,7 @@ def set_compiler_path(path_str, is_mlir=False): def download_latest_quingoc(): latest_release_url = "https://gitee.com/api/v5/repos/{owner}/{repo}/releases/latest".format( - owner="hpcl_quanta", repo="quingo-runtime") + owner="quingo", repo="quingoc-release") try: latest_release = get_text(latest_release_url) diff --git a/src/quingo/core/manager.py b/src/quingo/core/manager.py index d0013f13c472706699a265f623a126cb97a1aa7d..b4ec7406845c131975de3381c8acfb6f96ba787c 100755 --- a/src/quingo/core/manager.py +++ b/src/quingo/core/manager.py @@ -135,7 +135,8 @@ class Runtime_system_manager(): - mlir """ if (compiler_name not in self.supported_compilers): - raise ValueError("Found unsupported compiler: {}".format(compiler_name)) + raise ValueError( + "Found unsupported compiler: {}".format(compiler_name)) self.compiler_name = compiler_name @@ -182,7 +183,8 @@ class Runtime_system_manager(): try: self.backend = backend_hub.get_instance(backend_name) except Exception as e: - quingo_err("Cannot connect backend '{}' with the following error:".format(backend_name)) + quingo_err( + "Cannot connect backend '{}' with the following error:".format(backend_name)) quingo_err("{}".format(e)) quingo_info("To fix this problem, you could explicitly connect another " "backend use the the following method: \n" @@ -318,13 +320,16 @@ class Runtime_system_manager(): "The backend {} is not available.".format(backend.name())) if self.mode == 'state_vector' and not backend.is_simulator(): - raise ValueError("Cannot retrieve state vector from a non-simulator backend.") + raise ValueError( + "Cannot retrieve state vector from a non-simulator backend.") if self.verbose: - quingo_msg("Uploading the program to the backend {}...".format(backend.name())) + quingo_msg( + "Uploading the program to the backend {}...".format(backend.name())) if not backend.upload_program(self.qasm_file_path): - quingo_err("Failed to upload the program to the backend {}.".format(backend.name())) + quingo_err( + "Failed to upload the program to the backend {}.".format(backend.name())) quingo_info(" Suggestion: are you uploading QCIS program to an eQASM backend " "or eQASM program to a QCIS backend?\n" " If so, please specify the compiler and backend accordingly.") @@ -359,10 +364,12 @@ class Runtime_system_manager(): if compiler_name == 'mlir': quingoc_path = get_mlir_path() if quingoc_path is None: - quingo_err("Cannot find the mlir-based quingoc compiler in the system path.") + quingo_err( + "Cannot find the mlir-based quingoc compiler in the system path.") quingo_info( - "To resolve this problem, you can download quingoc from " - "https://gitee.com/hpcl_quanta/quingo-runtime/releases and save " + "To resolve this problem, you can install quingoc with two ways:\n" + "1. run the following command \"python -m quingo.install_quingoc\"\n" + "2. Dowload quingoc from https://gitee.com/quingo/quingoc-release/releases and save " "it at a directory in the system path \n" "or configure its path by calling this method inside python:\n" " `quingo.quingo_interface.set_mlir_compiler_path()`") @@ -432,8 +439,10 @@ class Runtime_system_manager(): compile_files.extend(user_files) compile_files.extend(default_files) - logger.debug(self.compose_xtext_cmd(compile_cmd_head, compile_files, print=True)) - compile_cmd = self.compose_xtext_cmd(compile_cmd_head, compile_files, False) + logger.debug(self.compose_xtext_cmd( + compile_cmd_head, compile_files, print=True)) + compile_cmd = self.compose_xtext_cmd( + compile_cmd_head, compile_files, False) else: raise ValueError("Found undefined compiler to use.") diff --git a/src/quingo/install_quingoc.py b/src/quingo/install_quingoc.py new file mode 100644 index 0000000000000000000000000000000000000000..862eb4ecdc86bc8dd678d8f6ac6af4aded02d815 --- /dev/null +++ b/src/quingo/install_quingoc.py @@ -0,0 +1,365 @@ +import pathlib +import re +import math +import requests +import json +import distutils.spawn +import subprocess +import platform +import zipfile +import sys +import shutil +import tempfile +import datetime +import tqdm +from pathlib import Path + +quingoc_owner = "quingo" +quingoc_release_repo = "quingoc-release" +lastest_quingoc_release_url = "https://gitee.com/api/v5/repos/{owner}/{repo}/releases/latest".format( + owner=quingoc_owner, repo=quingoc_release_repo) + +os_name_list = ['Linux', 'Windows', 'Darwin'] +os_dl_suffix = { + 'Linux': '.sh', + 'Windows': '.zip', + 'Darwin': '.dmg' + } + +def backup_compiler(quingoc_path): + + backup_path = quingoc_path.parent / "quingoc_backup" + + if not backup_path.exists(): + backup_path.mkdir(exist_ok=True) + + backup_file = quingoc_path.name + \ + datetime.datetime.now().strftime('%F') + + shutil.move(quingoc_path, backup_path/backup_file) + + print("Local quingoc has been backup at \"{}\".".format( + backup_path)) + + +def set_path_env_on_Linux(install_path): + """Set path environment to contain the milr quingo compiler on Linux. + """ + + ret_value = subprocess.run("echo $PATH", stdout=subprocess.PIPE, + stderr=subprocess.PIPE, text=True, shell=True) + + if ret_value.returncode != 0: + raise RuntimeError( + "Failed to retrieve system path using 'echo $PATH'.") + + if str(install_path.absolute()) in ret_value.stdout: + return + + bash_profile = Path.home() / '.bash_profile' + bashrc = Path.home() / '.bashrc' + shell_cmd = "if [ -f \"{bashrc_path}\" ]\nthen\n \ + echo 'export PATH={quingoc_dir_path}:$PATH' >> {bashrc_path}\n \ + elif [ -f \"{bash_profile_path}\" ]\nthen\n \ + echo 'export PATH={quingoc_dir_path}:$PATH' >> {bash_profile_path}\n \ + fi\n" + set_env_cmd = shell_cmd.format( + bashrc_path=bashrc, bash_profile_path=bash_profile, quingoc_dir_path=install_path) + + ret_value = subprocess.run(set_env_cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, text=True, shell=True) + + if(ret_value.returncode != 0): + raise RuntimeError("Failed add \"{}\" to path environment with the" + "following error: {}".format(install_path, ret_value.stderr)) + + +def install_on_Linux(mlir_compiler_path, old_version_path=None): + """Install quingo compiler on Linux. + """ + + mlir_compiler_path.chmod(0o744) + + if old_version_path is not None: + mlir_compiler_install_dir = old_version_path.parent + else: + mlir_compiler_install_dir = Path.home() / '.local' + + mlir_compiler_install_cmd = '"{}" --prefix="{}" --exclude-subdir'.format( + mlir_compiler_path, mlir_compiler_install_dir) + + ret_value = subprocess.run(mlir_compiler_install_cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, text=True, shell=True) + if(ret_value.returncode != 0): + raise RuntimeError("Failed to install lastest quingo compiler with the" + "following error: {}".format(ret_value.stderr)) + + if old_version_path is not None: + mlir_compiler_exec_path = mlir_compiler_install_dir + shutil.copy(str(mlir_compiler_install_dir / 'bin' / + 'quingoc'), str(mlir_compiler_exec_path)) + else: + mlir_compiler_exec_path = mlir_compiler_install_dir / 'bin' + + set_path_env_on_Linux(mlir_compiler_exec_path) + + print("Successfully installed the Lastest quingoc at \"{}\".".format( + mlir_compiler_exec_path)) + + +def set_path_on_Windows(install_path): + """Set path environment to contain the milr quingo compiler on Windows. + """ + # Nothing to do, quingo-runtime will search the default install path + # Default path is Path.home() / '.quingo' + + return + + +def install_on_Windows(mlir_compiler_path, old_version_path=None): + """Install quingo compiler on Windows. + """ + + if old_version_path is not None: + mlir_compiler_install_path = old_version_path.parent + else: + mlir_compiler_install_path = Path.home() / '.quingo' + + zip_file = zipfile.ZipFile(mlir_compiler_path) + zip_file.extractall(mlir_compiler_install_path) + zip_file.close() + + mlir_compiler_extract_path = mlir_compiler_install_path / mlir_compiler_path.stem + + files = [file for file in mlir_compiler_extract_path.glob( + "bin/*") if file.is_file()] + for file in files: + shutil.copy(file, mlir_compiler_install_path) + + shutil.rmtree(mlir_compiler_extract_path) + + set_path_on_Windows(mlir_compiler_install_path) + + print("Successfully installed the Lastest quingoc at \"{}\".".format( + mlir_compiler_install_path)) + + +def set_path_env_on_Darwin(install_path): + """Set path environment to contain the milr quingo compiler on Darwin. + """ + + set_path_env_on_Linux(install_path) + + +def install_on_Darwin(mlir_compiler_path, old_version_path=None): + """Install quingo compiler on Darwin. + """ + + if old_version_path is not None: + mlir_compiler_install_path = old_version_path.parent + mlir_compiler_exec_path = mlir_compiler_install_path + else: + mlir_compiler_install_path = Path.home() / '.local' + mlir_compiler_exec_path = mlir_compiler_install_path / 'bin' + + if not mlir_compiler_exec_path.exists(): + mlir_compiler_exec_path.mkdir(exist_ok=True) + + try: + # mount dmg file + mount_cmd = "hdiutil attach " + str(mlir_compiler_path) + + ret_value = subprocess.run(mount_cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, text=True, shell=True) + if(ret_value.returncode != 0): + raise RuntimeError("Failed to mount lastest quingo compiler dmg file with the" + "following error: {}".format(ret_value.stderr)) + + mlir_compiler_exec_file = pathlib.Path( + "/Volumes/" + mlir_compiler_path.stem) / 'quingoc.app' / 'Contents' / 'Resources' / 'bin' / 'quingoc' + + shutil.copy(str(mlir_compiler_exec_file), str(mlir_compiler_exec_path)) + + except Exception as e: + raise RuntimeError("Failed to copy quingo compiler {} to '{}' with the " + "following error: {}".format(mlir_compiler_exec_file, mlir_compiler_exec_path, e)) + + finally: + # umount dmg file + umount_cmd = "hdiutil detach " + \ + str("/Volumes/" + mlir_compiler_path.stem) + + ret_value = subprocess.run(umount_cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, text=True, shell=True) + if(ret_value.returncode != 0): + raise RuntimeError("Failed to umount lastest quingo compiler dmg file with the" + "following error: {}".format(ret_value.stderr)) + + set_path_env_on_Darwin(mlir_compiler_exec_path) + + print("Successfully installed the Lastest quingoc at \"{}\".".format( + mlir_compiler_exec_path)) + + +def install_compiler(os_name, mlir_compiler_path, old_version_path=None): + + if old_version_path is not None: + backup_compiler(old_version_path) + + if(os_name == 'Windows'): + install_on_Windows(mlir_compiler_path, + old_version_path) + if(os_name == 'Linux'): + install_on_Linux(mlir_compiler_path, + old_version_path) + if(os_name == 'Darwin'): + install_on_Darwin(mlir_compiler_path, + old_version_path) + + +def download_compiler(os_name, tmp_dir_name): + assert os_name in os_name_list + + dl_file_suffix = os_dl_suffix[os_name] + + try: + latest_release = requests.get(lastest_quingoc_release_url).text + release_info = json.loads(latest_release) + + except Exception as e: + raise RuntimeError("Failed to parse information retrieved from gitee with the " + "following error: {}".format(e)) + + assets = release_info['assets'] + quingoc_asset = None + for asset in assets: + if 'name' in asset and asset['name'].endswith(dl_file_suffix): + quingoc_asset = asset + break + if quingoc_asset is None: + raise RuntimeError( + "Failed to get quingo compiler release package for {} platform.".format(os_name)) + + quingoc_url = quingoc_asset['browser_download_url'] + \ + '/' + quingoc_asset['name'] + + try: + quingoc_response = requests.get(quingoc_url, stream=True) + except Exception as e: + raise RuntimeError("Failed to download package \"{}\" from gitee with the " + "following error: {}".format(quingoc_asset['name'], e)) + + data_size = math.ceil( + int(quingoc_response.headers['Content-Length'])/1024) + + mlir_compiler_path = tmp_dir_name / quingoc_asset['name'] + with mlir_compiler_path.open('wb') as tmp_dl_file: + print('Downloading quingoc from {} ({} KiB)'.format(quingoc_url, data_size)) + for data in tqdm.tqdm(iterable=quingoc_response.iter_content(1024), total=data_size, desc='progress', unit='KB'): + tmp_dl_file.write(data) + + return mlir_compiler_path + + +def download_and_install_latest_quingoc(old_version_path=None): + """Download the latest mlir quingo compiler. + """ + os_name = platform.system() + if os_name not in ['Linux', 'Windows', 'Darwin']: + raise SystemError( + "Currently pip installation does not support {}".format(os_name)) + + tmp_dir = tempfile.TemporaryDirectory() + tmp_dir_path = Path(tmp_dir.name) + + mlir_compiler_path = download_compiler(os_name, tmp_dir_path) + install_compiler(os_name, mlir_compiler_path, old_version_path) + + +def get_lastest_version(): + """Get lastest quingo compiler version + """ + + os_name = platform.system() + assert os_name in os_name_list + + dl_file_suffix = os_dl_suffix[os_name] + + try: + latest_release = requests.get(lastest_quingoc_release_url).text + release_info = json.loads(latest_release) + + except Exception as e: + raise RuntimeError("Failed to parse information retrieved from gitee with the " + "following error: {}".format(e)) + + assets = release_info['assets'] + quingoc_asset = None + for asset in assets: + if 'name' in asset and asset['name'].endswith(dl_file_suffix): + quingoc_asset = asset + break + if quingoc_asset is None: + raise RuntimeError( + "Failed to get quingo compiler release package for {} platform.".format(os_name)) + + find_version = re.search(r'\d+\.\d+\.\d+', quingoc_asset['name']) + if find_version is not None: + lastest_version = find_version.group() + else: + raise RuntimeError( + "Failed to get lastest version of quingo compiler from package \"{}\".".format(quingoc_asset['name'])) + + return lastest_version + + +def get_current_version(quingoc_path): + """Get current quingo compiler version + """ + + get_current_version_cmd = "{} --version".format(quingoc_path) + + ret_value = subprocess.run(get_current_version_cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, text=True, shell=True) + if(ret_value.returncode != 0): + raise RuntimeError("Failed to get local quingo compiler version with the" + "following error: {}".format(ret_value.stderr)) + + find_version = re.search(r'\d+\.\d+\.\d+', ret_value.stdout.split('\n')[0]) + if find_version is not None: + current_version = find_version.group() + else: + raise RuntimeError( + "Failed to get version of local quingo compiler from {}.".format(quingoc_path)) + + return current_version + + +def check_update(quingoc_path): + """Check local quingo compiler whether is latest version + """ + + current_version = get_current_version(quingoc_path) + lastest_version = get_lastest_version() + + if current_version == lastest_version: + print("Local quingoc is already the lastest version {}.".format(lastest_version)) + return False + else: + print("Local quingoc version ({}) is behind lastest version ({}). Update now.".format(current_version, lastest_version)) + return True + + +if __name__ == "__main__": + default_path = Path.home() / '.quingo' + quingoc_path = distutils.spawn.find_executable( + 'quingoc', str(default_path)) + + if quingoc_path is None: + quingoc_path = distutils.spawn.find_executable('quingoc') + + if quingoc_path is None: + download_and_install_latest_quingoc() + else: + if check_update(quingoc_path): + download_and_install_latest_quingoc(pathlib.Path(quingoc_path))