def contract_dir(contract_dir_hint): '''Given a hint, determine the contract directory. The contract directory is the container for the project of a contract. The hint is probed to be one of the following pieces of information: the absolute path to a contract directory; the relative path to a contract directory, relative to the directory set with the ``contract_workspace_`` variable; the relative path to a contract directory, relative to the ``contracts`` directory in the repository of EOSFactory; the relative path to a contract directory, relative to the ``contracts`` directory in the repository of EOSIO. ''' contract_dir_hint = utils.wslMapWindowsLinux(contract_dir_hint) # ? the absolute path to a contract directory trace = contract_dir_hint + "\n" if os.path.isfile(contract_dir_hint): contract_dir_hint = os.path.dirname(contract_dir_hint) if os.path.isabs(contract_dir_hint): return contract_dir_hint # ? the relative path to a contract directory, relative to the directory # set with the 'contract_workspace_' variable contract_dir_ = os.path.join(config_value(contract_workspace_), contract_dir_hint) trace = trace + contract_dir_ + "\n" if os.path.isdir(contract_dir_): return contract_dir_ # ? the relative path to a contract directory, relative to the # ``contracts`` directory in the repository of EOSFactory contract_dir_ = os.path.join(eosf_dir(), CONTRACTS_DIR, contract_dir_hint) trace = trace + contract_dir_ + "\n" if os.path.isdir(contract_dir_): return contract_dir_ # ? the relative path to a contract directory, relative to the # ``contracts`` directory in the repository of EOSIO contract_dir_ = os.path.join(config_value(eosio_repository_dir_), EOSIO_CONTRACT_DIR, contract_dir_hint) trace = trace + contract_dir_ + "\n" if os.path.isdir(contract_dir_): return contract_dir_ raise errors.Error(''' Cannot determine the contract directory. Tried path list: {} '''.format(trace))
def eosf_dir(): '''The absolute directory of the EOSFactory installation. ''' path = os.path.realpath(os.path.join( os.path.realpath(__file__), FROM_HERE_TO_EOSF_DIR)) if os.path.exists(path): return path raise errors.Error(''' Cannot determine the root directory of the EOSFactory installation. The path to the file 'config.py' is '{}'. The expected installation path, which is '{}', is reported as non-existent. '''.format(__file__, path), translate=False)
def first_valid_path(config_list, findFile=None, raise_error=True): '''Given a key to the config list, get a valid file system path. The key may map to a path either absolute, or relative either to the EOSIO or EOSF repositories. Also, the path can be relative to the ``HOME`` environment variable. ''' values = config_values(config_list) for path in values: if "${HOME}" in path: home = None if "HOME" in os.environ: home = os.environ["HOME"] if home: path = path.replace("${HOME}", home) if findFile: if os.path.exists(os.path.join(path, findFile)): return path else: if os.path.exists(path): return path if os.path.isabs(path): if findFile: if os.path.exists(os.path.join(path, findFile)): return path else: if os.path.exists(path): return path else: full_path = os.path.join(eosf_dir(), path) if findFile: if os.path.exists(os.path.join(full_path, findFile)): return full_path else: if os.path.exists(full_path): return full_path if raise_error: raise errors.Error(''' Cannot find any path for '{}'. '''.format(config_list[0]))
def contract_dir(contract_dir_hint): '''Given a hint, determine the contract root directory. The ``contract_dir_hint`` is tested to be either - an absolute path, or - a path relative to either - the directory given with :func:`contract_workspace`, or - the directory given with :func:`eosf_dir` ``/contracts``. Args: contract_dir_hint (path): A directory path, may be not absolute. Raises: .core.errors.Error: If the result is not defined. ''' contract_dir_hint = utils.wslMapWindowsLinux(contract_dir_hint) # ? the absolute path to a contract directory trace = contract_dir_hint + "\n" if os.path.isfile(contract_dir_hint): contract_dir_hint = os.path.dirname(contract_dir_hint) if os.path.isabs(contract_dir_hint): return os.path.realpath(contract_dir_hint) # ? the relative path to a contract directory, relative to the directory # set with the 'contract_workspace_dir()' function contract_dir_ = os.path.join(contract_workspace_dir(), contract_dir_hint) trace = trace + contract_dir_ + "\n" if os.path.isdir(contract_dir_): return os.path.realpath(contract_dir_) # ? the relative path to a contract directory, relative to # 'get_app_data_dir()/contracts' contract_dir_ = os.path.join(get_app_data_dir(), CONTRACTS_DIR, contract_dir_hint) trace = trace + contract_dir_ + "\n" if os.path.isdir(contract_dir_): return os.path.realpath(contract_dir_) raise errors.Error(''' Cannot determine the contract directory. Tried: {} '''.format(trace), translate=False)
def config_value_checked(config_list): '''Get the first item from :func:`.config_values`. Raise an error if fails. Args: config_list (tuple): A configure list tuple. Raises: .core.errors.Error: If the result is not defined. ''' retval = config_value(config_list) if not retval is None: return retval raise errors.Error(''' The value of {} is not defined. Define it in the config file {} '''.format(config_list[0], config_file()))
def is_linked_package(): is_linked = os.path.exists(os.path.join(eosf_dir(), CONFIG_DIR)) is_copied = not is_linked and get_app_data_dir() if (not is_linked) and (not is_copied): raise errors.Error(''' Cannot determine the configuration directory. {} {} {} '''.format(os.path.join(eosf_dir(), CONFIG_DIR), os.path.join(APP_DATA_DIR_USER[0], CONFIG_DIR), os.path.join(APP_DATA_DIR_SUDO[0], CONFIG_DIR)), translate=False) if is_linked and is_copied: is_linked = True return is_linked
def verify_testnet_production(): head_block_num = 0 try: # if running, json is produced head_block_num = cleos_get.GetInfo(is_verbose=False).head_block except: pass domain = "LOCAL" if is_local_testnet() else "REMOTE" if not head_block_num: raise errors.Error(''' {} testnet is not running or is not responding @ {}. '''.format(domain, setup.nodeos_address())) else: logger.INFO(''' {} testnet is active @ {}. '''.format(domain, setup.nodeos_address())) return head_block_num
def eoside_libs_dir(): '''The directory for contract links. It may be set with *LIBS* entry in the *config.json* file, see :func:`.current_config`. ''' dir = libs_[1] if not os.path.isabs(dir): dir = os.path.join(get_app_data_dir(), libs_[1]) if not os.path.exists(dir): raise errors.Error(''' Cannot find the libs directory {}. It may be set with {} entry in the config.json file. '''.format(dir, libs_[0]), translate=False) return dir
def eoside_includes_dir(): '''The directory for contract definition includes. It may be set with *INCLUDE* entry in the *config.json* file, see :func:`.current_config`. ''' dir = includes_[1] if not os.path.isabs(dir): dir = os.path.join(get_app_data_dir(), includes_[1]) if not os.path.exists(dir): raise errors.Error(''' Cannot find the include directory {}. It may be set with {} entry in the config.json file. '''.format(dir, includes_[0]), translate=False) return dir
def is_wallet_defined(logger, globals=None): global wallet_globals if not wallet_globals is None: return True global wallet_singleton wallet_singleton = wallet.Wallet.wallet_single if wallet_singleton is None: wallet.create_wallet(wallet_globals=globals) wallet_singleton = wallet.Wallet.wallet_single if wallet_singleton is None: raise errors.Error(''' Cannot find any `Wallet` object. ''') wallet_globals = wallet.Wallet.globals return True
def write_config_map(map): '''Write the given json object to *config.json*. Args: map (json): The json object to be saved. Raises: .core.errors.Error: If the JSON object cannot be saved. ''' path = config_file() if os.path.exists(path): with open(path, "w+") as output: output.write(json.dumps(map, indent=4)) return raise errors.Error(''' Cannot find the config file. ''')
def genesis_json(): '''File to read Genesis State from. It may be changed with *EOSIO_GENESIS_JSON* entry in the *config.json* file, see :func:`.current_config`. ''' path = first_valid_path(genesis_json_, raise_error=False) if not path: path = os.path.join(config_dir(), "genesis.json") if not os.path.exists(path): raise errors.Error(''' Cannot find any path for '{}'. Tried: {} '''.format(genesis_json_[0], genesis_json_[1]), translate=False) return path
def delete(wallet, is_verbose=True): name = wallet_arg(wallet) file = wallet_file(name) if os.path.isfile(file): try: os.remove(file) except Exception as e: raise errors.Error(str(e)) if is_verbose: logger.OUT("Deleted wallet: '{}'".format(name)) return True if is_verbose: logger.OUT(''' There is not any wallet file named '{}' '''.format(name)) return False
def is_name_taken(self, account_object_name, account_name): while True: account_map_json = manager.account_map(self) if account_map_json is None: return False is_taken = False for name, object_name in account_map_json.items(): if object_name == account_object_name: if not name == account_name: logger.OUT(''' The given account object name ``{}`` points to an existing account, of the name {}, mapped in a file in directory: {} Cannot overwrite it. However, you can free the name by changing the mapping. Do you want to edit the file? '''.format(account_object_name, name, self.wallet_dir)) is_taken = True break if is_taken: temp = None if account_object_name in Wallet.globals: temp = Wallet.globals[account_object_name] del Wallet.globals[account_object_name] answer = input("y/n <<< ") if answer == "y": manager.edit_account_map() continue else: if temp: Wallet.globals[account_object_name] = temp raise errors.Error(''' Use the function 'manager.edit_account_map(text_editor="nano")' to edit the file. ''') else: break
def runInThread(): p = subprocess.run( command_line, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) err_msg = p.stderr.decode("ISO-8859-1") if "error" in err_msg and not "exit shutdown" in err_msg: raise errors.Error(err_msg) elif not err_msg or "exit shutdown" in err_msg: logger.OUT( ''' Just another instability incident of the ``nodeos`` executable. Rerun the script. ''' ) else: print(err_msg)
def account_map(logger=None): '''Return json account map Attempt to open the account map file named ``setup.account_map``, located in the wallet directory ``config.keosd_wallet_dir()``, to return its json contents. If the file does not exist, return an empty json. If the file is corrupted, offer editing the file with the ``nano`` linux editor. Return ``None`` if the the offer is rejected. ''' wallet_dir_ = config.keosd_wallet_dir(raise_error=False) if not wallet_dir_: return {} path = os.path.join(wallet_dir_, setup.account_map) while True: try: # whether the setup map file exists: with open(path, "r") as input_file: return json.load(input_file) except Exception as e: if isinstance(e, FileNotFoundError): return {} else: logger.OUT(''' The account mapping file is misformed. The error message is: {} Do you want to edit the file? '''.format(str(e))) answer = input("y/n <<< ") if answer == "y": edit_account_map() continue else: raise errors.Error(''' Use the function 'efman.edit_account_map(text_editor="nano")' or the corresponding method of any object of the 'eosfactory.wallet.Wallet` class to edit the file. ''') return None
def on_nodeos_error(clear=False): node_stop() args_ = args(clear) args_.insert(0, config.node_exe()) command_line = " ".join(args_) raise errors.Error(''' The local ``nodeos`` failed to start twice in sequence. Perhaps, something is wrong with configuration of the system. See the command line issued: ''') print("\n{}\n".format(command_line)) logger.INFO(''' Now, see the result of an execution of the command line: ''') def runInThread(): p = subprocess.run( command_line, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) err_msg = p.stderr.decode("ISO-8859-1") if "error" in err_msg and not "exit shutdown" in err_msg: raise errors.Error(err_msg) elif not err_msg or "exit shutdown" in err_msg: logger.OUT( ''' Just another instability incident of the ``nodeos`` executable. Rerun the script. ''' ) else: print(err_msg) thread = threading.Thread(target=runInThread) thread.start() time.sleep(10) node_stop() exit()
def contract_source_files(contract_dir_hint): contract_dir_ = contract_dir(utils.wslMapWindowsLinux(contract_dir_hint)) trace = contract_dir_ + "\n" source_path = contract_dir_ srcs = source_files(source_path) if srcs: return (source_path, srcs) source_path = os.path.join(contract_dir_, "src") trace = trace + source_path + "\n" srcs = source_files(source_path) if srcs: return (source_path, srcs) raise errors.Error(''' Cannot find any contract source directory. Tried path list: {} '''.format(trace))
def get_c_cpp_properties(contract_dir=None, c_cpp_properties_path=None): if not contract_dir: contract_dir = os.getcwd() if not c_cpp_properties_path: c_cpp_properties_path = os.path.join( contract_dir, ".vscode/c_cpp_properties.json") else: c_cpp_properties_path = linuxize_path(c_cpp_properties_path) if not os.path.exists(c_cpp_properties_path): c_cpp_properties_path = os.path.join( contract_dir, ".vscode/c_cpp_properties.json") if os.path.exists(c_cpp_properties_path): try: with open(c_cpp_properties_path, "r") as f: return json.loads(f.read()) except Exception as e: raise errors.Error(str(e)) else: return json.loads(resolve_home(vscode.c_cpp_properties()))
def kill(name): pids = get_pid(name) count = 10 for pid in pids: p = psutil.Process(pid) p.terminate() while count > 0: time.sleep(1) if not psutil.pid_exists(pid): break count = count -1 if count <= 0: raise errors.Error(''' Failed to kill {}. Pid is {}. '''.format( os.path.splitext(os.path.basename(config.node_exe()))[0], str(pids)) ) return pids
def __init__(self, js): self.json = None cl = ["node", "-e"] js = utils.heredoc(js) cl.append(js) if setup.is_print_command_line: print("javascript:") print("___________") print("") print(js) print("") process = subprocess.run(cl, stdout=subprocess.PIPE, stderr=subprocess.PIPE) err_msg = process.stderr.decode("utf-8") if err_msg: raise errors.Error(err_msg) self.json = json.loads(process.stdout.decode("utf-8"))
def read_map(file_name, text_editor="nano"): '''Return json account map Attempt to open the account map file named ``setup.account_map``, located in the wallet directory ``config.keosd_wallet_dir()``, to return its json contents. If the file does not exist, return an empty json. If the file is corrupted, offer editing the file with the ``nano`` linux editor. Return ``None`` if the the offer is rejected. ''' wallet_dir_ = config.keosd_wallet_dir() path = os.path.join(wallet_dir_, file_name) while True: try: # whether the setup map file exists: with open(path, "r") as input_file: return json.load(input_file) except Exception as e: if isinstance(e, FileNotFoundError): return {} else: logger.ERROR(''' The json file {} is misformed. The error message is: {} Do you want to edit the file? '''.format(str(path), str(e)), translate=False) answer = input("y/n <<< ") if answer == "y": utils.spawn([text_editor, path]) continue else: raise errors.Error(''' Use the function 'manager.edit_account_map()' to edit the file. ''', translate=False)
def first_valid_which(config_list, find_file=None, raise_error=True): '''Given a key to the config list, get a valid file system path. Applicable if the *config_list* argument refers to a file path. The path may be absolute or relative to the root of the EOSFactory installation. Also, the path may be relative to the *HOME* environment variable. Args: config_list (tuple): A configure list tuple. find_file (str): If set, the given file has to exist. raise_error (bool): If set, raise an error on failure. Raises: .core.errors.Error: If the *raise_error* argument is set and the \ result is not defined. ''' values = config_values(config_list) if values[0]: for path in values: if os.path.isabs(path): if find_file: if os.path.exists(os.path.join(path, find_file)): return path else: if utils.which(path): return path if raise_error: config_values(config_list) raise errors.Error(''' Cannot find any path for '{}'. Tried: {} '''.format(config_list[0], config_list[1]), translate=False) else: return None
def get_app_data_dir(): if APP_DATA_DIR_SUDO[1] in __file__: app_data_dir = APP_DATA_DIR_SUDO[0] elif os.path.expandvars(APP_DATA_DIR_USER[1]) in __file__: app_data_dir = APP_DATA_DIR_USER[0] else: app_data_dir = eosf_dir() if app_data_dir and os.path.exists(app_data_dir): return app_data_dir raise errors.Error(''' Cannot determine the directory of application data. Tried: '{}', '{}', '{}'. The chosen path is '{}', but it does not exist, seemingly. '''.format(APP_DATA_DIR_SUDO[0], APP_DATA_DIR_USER[0], eosf_dir(), app_data_dir), translate=False)
def contract_source_files(contract_dir_hint): '''List files CPP/C and ABI files from directory given a hint. Args: contract_dir_hint (str): An argument to the function :func:`.contract_dir` Raises: .core.errors.Error: If the list is empty. ''' contract_dir_ = contract_dir(contract_dir_hint) trace = contract_dir_ + "\n" search_dir = contract_dir_ srcs = source_files(search_dir, [".c", ".cpp",".cxx", ".c++"], recursively=True) if srcs: return (search_dir, srcs) raise errors.Error(''' Cannot find any contract source directory. Tried: {} '''.format(trace), translate=False)
def node_probe(verbosity=None): count = 15 num = 5 block_num = None while True: time.sleep(1) try: if setup.node_api == "cleos": import eosfactory.core.cleos as cleos elif setup.node_api == "eosjs": import eosfactory.core.eosjs as cleos get_info = cleos.GetInfo(is_verbose=0) head_block_num = int(get_info.json["head_block_num"]) except: head_block_num = 0 finally: print(".", end="", flush=True) if block_num is None: block_num = head_block_num if head_block_num - block_num >= num: print() logger.INFO( ''' Local node is running. Block number is {} '''.format(head_block_num), verbosity) break count = count - 1 if count <= 0: raise errors.Error(''' The local node does not respond. ''')
def eosfactory_data(): '''Data directory. For developer's installation, data is in the root of the installation. .: wsl_root.sh config: config.ini, config.json, genesis.json, ... contracts: eosio_token, hello_world, tic_tac_toe, ... templates: contracts, ... includes: eoside, ... libs: ... ''' tested = [] is_not_linked = is_site_package() if not is_not_linked: path = eosf_dir() tested.append(path) if os.path.exists(os.path.join(path, "config", "config.ini")): return path elif is_not_linked == 1: for path in eosfactory_data_[1]: tested.append(path) if os.path.exists(os.path.join(path, "config", "config.ini")): return path elif is_not_linked == 2: for path in eosfactory_data_[2]: tested.append(path) if os.path.exists(os.path.join(path, "config", "config.ini")): return path msg = "Cannot determine the directory of application data. Tried:" for path in tested: msg = '''{} {} '''.format(msg, path) raise errors.Error(msg, translate=False)
def __init__(self, account, contract_dir=None, abi_file=None, wasm_file=None, permission=None, expiration_sec=None, skip_sign=0, dont_broadcast=0, force_unique=0, max_cpu_usage=0, max_net_usage=0, ref_block=None, delay_sec=0): if not isinstance(account, eosfactory.shell.account.Account) and not isinstance( account, core_account.Eosio): raise errors.Error(""" The account object has to be of the type ``eosfactory.shell.account.Account``. """) super().__init__(contract_dir, abi_file=abi_file, wasm_file=wasm_file) self.account = account self.permission = permission self.expiration_sec = expiration_sec self.skip_sign = skip_sign self.dont_broadcast = dont_broadcast self.force_unique = force_unique self.max_cpu_usage = max_cpu_usage self.max_net_usage = max_net_usage self.ref_block = ref_block self.delay_sec = delay_sec self.contract = None self._console = None
def clear_testnet_cache(): ''' Remove wallet files associated with the current testnet. ''' if not setup.file_prefix(): return logger.TRACE(''' Removing testnet cache for prefix `{}` '''.format(setup.file_prefix())) teos.kill_keosd() # otherwise the manager may protects the wallet files wallet_dir = config.keosd_wallet_dir() files = os.listdir(wallet_dir) try: for file in files: if file.startswith(setup.file_prefix()): os.remove(os.path.join(wallet_dir, file)) except Exception as e: raise errors.Error(''' Cannot remove testnet cache. The error message is: {} '''.format(str(e))) logger.TRACE(''' Testnet cache successfully removed. ''')
def process(command_line, error_message='', shell=False): import subprocess p = subprocess.run(command_line, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout = p.stdout.decode("ISO-8859-1").strip() stderr = p.stderr.decode("ISO-8859-1").strip() if stderr: raise errors.Error(''' {} command line: ============= {} error message: ============== {} '''.format(error_message, " ".join(command_line), stderr)) return stdout