def _get_solc_version_list() -> Tuple[List, List]: global AVAILABLE_SOLC_VERSIONS installed_versions = [Version(i[1:]) for i in solcx.get_installed_solc_versions()] if AVAILABLE_SOLC_VERSIONS is None: try: AVAILABLE_SOLC_VERSIONS = [Version(i[1:]) for i in solcx.get_available_solc_versions()] except ConnectionError: if not installed_versions: raise ConnectionError("Solc not installed and cannot connect to GitHub") AVAILABLE_SOLC_VERSIONS = installed_versions return AVAILABLE_SOLC_VERSIONS, installed_versions
def pytest_configure(config): global VERSIONS if config.getoption("--no-install"): VERSIONS = solcx.get_installed_solc_versions() return try: VERSIONS = solcx.get_available_solc_versions() except ConnectionError: raise pytest.UsageError( "ConnectionError while attempting to get solc versions.\n" "Use the --no-install flag to only run tests against already installed versions." )
def pytest_configure(config): if config.getoption("--target") == "plugin" and config.getoption( "numprocesses"): raise pytest.UsageError( "Cannot use xdist with plugin tests, try adding the '-n 0' flag") if config.getoption("--evm"): # reformat evm options - only do this once to avoid repeat queries for latest solc version solc_versions, evm_verions, runs = [ i.split(",") for i in config.option.evm ] runs = [int(i) for i in runs] if "latest" in solc_versions: latest_version = solcx.get_available_solc_versions()[0] solc_versions.remove("latest") solc_versions.append(latest_version) config.option.evm = (evm_verions, runs, solc_versions)
def get_supported_solc_versions(): global _SOLC_VERSIONS global _SOLC_VERSIONS_LAST_UPDATE # Cache the result for one hour if len(_SOLC_VERSIONS) != 0 and _SOLC_VERSIONS_LAST_UPDATE >= time.time() - 3600: return _SOLC_VERSIONS try: new_versions = get_available_solc_versions() _SOLC_VERSIONS = sorted((SolidityVersion(v[1:]) for v in new_versions)) _SOLC_VERSIONS_LAST_UPDATE = time.time() except requests.exceptions.RequestException: # If offline, work with installed versions logging.info('Fetching the latest compiler releases failed, relying on known versions.') return _SOLC_VERSIONS
import os.path import asyncio from time import time from typing import Optional, Sequence import solcx from web3.contract import ContractConstructor, ContractFunctions from eth_abi import decode_abi from web3._utils.abi import get_abi_output_types from web3._utils.contracts import prepare_transaction from web3._utils.datatypes import PropertyCheckingFactory from eth_utils import to_checksum_address, hexstr_if_str, to_bytes from asynther.common import SubModule from asynther.account import Account, NeedPrivateKey solcx_version = solcx.get_available_solc_versions()[0] if solcx_version not in solcx.get_installed_solc_versions(): solcx.install_solc(solcx_version) class Interface(dict): """ Contract interface """ def __init__(self, source_file: str, allow_paths: Optional[Sequence[str]] = None): assert isinstance(source_file, str) and os.path.exists(source_file) assert allow_paths is None or \ (isinstance(allow_paths, (tuple, list)) and all(os.path.exists(path) for path in allow_paths)) allow_paths = ','.join(allow_paths) if allow_paths is not None else allow_paths for name, interface in solcx.compile_files([source_file], allow_paths=allow_paths).items(): if name.startswith(source_file + ':'): super().__init__(interface)
def find_solc_versions(contracts, install_needed=False, install_latest=False, silent=True): '''Analyzes contract pragmas and determines which solc version(s) to use. Args: contracts: a dictionary in the form of {'path': "source code"} install_needed: if True, will install when no installed version matches the contract pragma install_latest: if True, will install when a newer version is available than the installed one silent: enables verbose reporting Returns: dictionary of {'version': ['path', 'path', ..]} ''' installed_versions = [ Version(i[1:]) for i in solcx.get_installed_solc_versions() ] try: available_versions = [ Version(i[1:]) for i in solcx.get_available_solc_versions() ] except ConnectionError: if not installed_versions: raise ConnectionError( "Solc not installed and cannot connect to GitHub") available_versions = installed_versions pragma_regex = re.compile(r"pragma +solidity([^;]*);") version_regex = re.compile(r"(([<>]?=?|\^)\d+\.\d+\.\d+)+") pragma_specs = dict((i, set()) for i in contracts) to_install = set() for path, source in contracts.items(): try: pragma_string = next(pragma_regex.finditer(source))[0] except StopIteration: raise PragmaError(f"No version pragma in '{path}'") from None # convert pragma to Version objects comparator_set_range = pragma_string.replace(" ", "").split('||') for comparator_set in comparator_set_range: spec = Spec(*(i[0] for i in version_regex.findall(comparator_set))) spec = _standardize_spec(spec) pragma_specs[path].add(spec) # if no installed version of solc matches the pragma, find the latest available version if not next( (i for i in pragma_specs[path] if i.select(installed_versions)), None): try: version = _select_max(pragma_specs[path], available_versions) to_install.add(version) except ValueError: raise PragmaError( f"No installable solc version matching '{pragma_string}' in '{path}'" ) from None if not install_needed: raise IncompatibleSolcVersion( f"No installed solc version matching '{pragma_string}' in '{path}'" ) # install new versions if needed if to_install: install_solc(*to_install) installed_versions = [ Version(i[1:]) for i in solcx.get_installed_solc_versions() ] # organize source paths by latest available solc version compiler_versions = {} new_versions = set() for path, spec_list in pragma_specs.items(): version = _select_max(spec_list, installed_versions) compiler_versions.setdefault(str(version), []).append(path) latest = _select_max(spec_list, available_versions) if latest > version: new_versions.add(str(latest)) if new_versions: if install_latest: install_solc(*new_versions) return find_solc_versions(contracts) if not silent: print( f"New compatible solc version{'s' if len(new_versions) > 1 else ''}" f" available: {', '.join(new_versions)}") return compiler_versions
def find_solc_versions( contracts: Dict[str, str], install_needed: bool = False, install_latest: bool = False, silent: bool = True, ) -> Dict: """Analyzes contract pragmas and determines which solc version(s) to use. Args: contracts: a dictionary in the form of {'path': "source code"} install_needed: if True, will install when no installed version matches the contract pragma install_latest: if True, will install when a newer version is available than the installed one silent: set to False to enable verbose reporting Returns: dictionary of {'version': ['path', 'path', ..]} """ installed_versions = [ Version(i[1:]) for i in solcx.get_installed_solc_versions() ] try: available_versions = [ Version(i[1:]) for i in solcx.get_available_solc_versions() ] except ConnectionError: if not installed_versions: raise ConnectionError( "Solc not installed and cannot connect to GitHub") available_versions = installed_versions pragma_regex = re.compile(r"pragma +solidity([^;]*);") pragma_specs: Dict = {} to_install = set() new_versions = set() for path, source in contracts.items(): pragma_string = next(pragma_regex.finditer(source), None) if pragma_string is None: raise PragmaError(f"No version pragma in '{path}'") pragma_specs[path] = NpmSpec(pragma_string.groups()[0]) version = pragma_specs[path].select(installed_versions) if not version and not (install_needed or install_latest): raise IncompatibleSolcVersion( f"No installed solc version matching '{pragma_string[0]}' in '{path}'" ) # if no installed version of solc matches the pragma, find the latest available version latest = pragma_specs[path].select(available_versions) if not version and not latest: raise PragmaError( f"No installable solc version matching '{pragma_string[0]}' in '{path}'" ) if not version or (install_latest and latest > version): to_install.add(latest) elif latest > version: new_versions.add(str(version)) # install new versions if needed if to_install: install_solc(*to_install) installed_versions = [ Version(i[1:]) for i in solcx.get_installed_solc_versions() ] elif new_versions and not silent: print( f"New compatible solc version{'s' if len(new_versions) > 1 else ''}" f" available: {', '.join(new_versions)}") # organize source paths by latest available solc version compiler_versions: Dict = {} for path, spec in pragma_specs.items(): version = spec.select(installed_versions) compiler_versions.setdefault(str(version), []).append(path) return compiler_versions