Ejemplo n.º 1
0
def find_best_solc_version(
    contract_sources: Dict[str, str],
    install_needed: bool = False,
    install_latest: bool = False,
    silent: bool = True,
) -> str:
    """
    Analyzes contract pragmas and finds the best version compatible with all sources.

    Args:
        contract_sources: 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: version string
    """

    available_versions, installed_versions = _get_solc_version_list()

    for path, source in contract_sources.items():

        pragma_string = next(PRAGMA_REGEX.finditer(source), None)
        if pragma_string is None:
            raise PragmaError(f"No version pragma in '{path}'")
        pragma_spec = NpmSpec(pragma_string.groups()[0])
        installed_versions = [
            i for i in installed_versions if i in pragma_spec
        ]
        available_versions = [
            i for i in available_versions if i in pragma_spec
        ]

    if not available_versions:
        raise IncompatibleSolcVersion(
            "No installable solc version compatible across all sources")

    if not installed_versions and not (install_needed or install_latest):
        raise IncompatibleSolcVersion(
            "No installed solc version compatible across all sources")

    if max(available_versions) > max(installed_versions,
                                     default=Version("0.0.0")):
        if install_latest or (install_needed and not installed_versions):
            install_solc(max(available_versions))
            return str(max(available_versions))
        if not silent:
            print(
                f"New compatible solc version available: {max(available_versions)}"
            )

    return str(max(installed_versions))
Ejemplo n.º 2
0
def set_solc_version(version: Union[str, Version]) -> str:
    """Sets the solc version. If not available it will be installed."""
    if not isinstance(version, Version):
        version = Version(version.lstrip("v"))
    if version < Version("0.4.22"):
        raise IncompatibleSolcVersion("Brownie only supports Solidity versions >=0.4.22")
    try:
        solcx.set_solc_version(version, silent=True)
    except solcx.exceptions.SolcNotInstalled:
        if version not in _get_solc_version_list()[0]:
            raise IncompatibleSolcVersion(
                f"Cannot install Solidity v{version} on this OS. You may be able to "
                f"manually compile from source with `solcx.compile_solc('{version}')`"
            )
        install_solc(version)
        solcx.set_solc_version(version, silent=True)
    return str(solcx.get_solc_version())
Ejemplo n.º 3
0
def set_solc_version(version: str) -> str:
    """Sets the solc version. If not available it will be installed."""
    if Version(version.lstrip("v")) < Version("0.4.22"):
        raise IncompatibleSolcVersion("Brownie only supports Solidity versions >=0.4.22")
    try:
        solcx.set_solc_version(version, silent=True)
    except solcx.exceptions.SolcNotInstalled:
        install_solc(version)
        solcx.set_solc_version(version, silent=True)
    return str(solcx.get_solc_version())
Ejemplo n.º 4
0
def set_solc_version(version):
    '''Sets the solc version. If not available it will be installed.'''
    if Version(version.lstrip('v')) < Version('0.4.22'):
        raise IncompatibleSolcVersion(
            "Brownie only supports Solidity versions >=0.4.22")
    try:
        solcx.set_solc_version(version, silent=True)
    except solcx.exceptions.SolcNotInstalled:
        install_solc(version)
        solcx.set_solc_version(version, silent=True)
    return solcx.get_solc_version_string()
Ejemplo n.º 5
0
def find_solc_versions(
    contract_sources: 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:
        contract_sources: 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', ..]}
    """

    available_versions, installed_versions = _get_solc_version_list()

    pragma_specs: Dict = {}
    to_install = set()
    new_versions = set()

    for path, source in contract_sources.items():
        pragma_specs[path] = sources.get_pragma_spec(source, path)
        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_specs[path]}' 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 IncompatibleSolcVersion(
                f"No installable solc version matching '{pragma_specs[path]}' in '{path}'"
            )

        if not version or (install_latest and latest > version):
            to_install.add(latest)
        elif latest and latest > version:
            new_versions.add(str(version))

    # install new versions if needed
    if to_install:
        install_solc(*to_install)
        installed_versions = 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
Ejemplo n.º 6
0
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
Ejemplo n.º 7
0
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