diff --git a/pyproject.toml b/pyproject.toml index a041678..50b61b2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "solc_detect" -version = "0.0.7" +version = "0.0.8" authors = [{name="Ta Quang Trung"},] description = "A tool to detect Solidity compiler version required by smart contracts" dynamic = ["dependencies"] diff --git a/solc_detect/__init__.py b/solc_detect/__init__.py index 4304369..cf8a563 100644 --- a/solc_detect/__init__.py +++ b/solc_detect/__init__.py @@ -16,3 +16,7 @@ def find_best_solc_version(input_file): def find_best_solc_version_for_pragma(pragma_version): """Find the best version of Solc compiler for pragma.""" return solc_detect.find_best_solc_version_for_pragma(pragma_version) + +def find_all_best_solc_versions_for_pragma(pragma_version): + """Find all the best versions of Solc compiler for pragma.""" + return solc_detect.find_all_best_solc_versions_for_pragma(pragma_version) diff --git a/solc_detect/__main__.py b/solc_detect/__main__.py index 11d4ac0..afddbaa 100644 --- a/solc_detect/__main__.py +++ b/solc_detect/__main__.py @@ -38,6 +38,16 @@ def configure_cli_arguments(): help="", ) + # Quiet mode, print only the best version. + arg_parser.add_argument( + "-a", + "--all-best-verions", + dest="all_best_versions", + action="store_true", + default=False, + help="Finding all best versions for each minor Solc version.", + ) + # Help arg_parser.add_argument( "-h", @@ -73,15 +83,23 @@ def main(): arg_parser.print_usage() arg_parser.exit() - pragma_version = solc_detect.find_pragma_solc_version(input_file) - if not args.quiet: - print("Detected pragmas:", pragma_version) - - best_version = solc_detect.find_best_solc_version_for_pragma(pragma_version) + pragmas = solc_detect.find_pragma_solc_version(input_file) if not args.quiet: - print("Best version:", best_version) + print("Detected pragmas:", pragmas) + + if args.all_best_versions: + best_version = solc_detect.find_all_best_solc_versions_for_pragma(pragmas) + if not args.quiet: + print("All best versions:", best_version) + else: + print(best_version) + return else: - print(best_version) + best_version = solc_detect.find_best_solc_version_for_pragma(pragmas) + if not args.quiet: + print("Best version:", best_version) + else: + print(best_version) if __name__ == "__main__": diff --git a/solc_detect/solc_detect.py b/solc_detect/solc_detect.py index fda87f4..ae511fb 100644 --- a/solc_detect/solc_detect.py +++ b/solc_detect/solc_detect.py @@ -51,16 +51,39 @@ def find_best_solc_version_for_pragma(pragma_versions) -> Optional[str]: # First, use `semantic_version` module to find the best version all_semvers = [semantic_version.Version(v) for v in group] version_spec = semantic_version.NpmSpec(constraint) - if (best_version := version_spec.select(all_semvers)): + if best_version := version_spec.select(all_semvers): return str(best_version) except ValueError: # If errors occur, then use `node_semver` module to find it - if (best_version := nodesemver.max_satisfying(group, constraint)): + if best_version := nodesemver.max_satisfying(group, constraint): return str(best_version) # Unable to find a suitable version return None +def find_all_best_solc_versions_for_pragma(pragma_versions) -> List[str]: + """Find multiple best versions of Solc compiler for a pragma version. These + versions are the latest patches of each version satisfying the required + pragmas. + """ + version_groups = enumerate_and_group_solc_version_by_minor_version() + constraint = " ".join(pragma_versions) + + best_versions: List[str] = [] + for group in version_groups: + try: + # First, use `semantic_version` module to find the best version + all_semvers = [semantic_version.Version(v) for v in group] + version_spec = semantic_version.NpmSpec(constraint) + if best_version := version_spec.select(all_semvers): + best_versions.append(str(best_version)) + except ValueError: + # If errors occur, then use `node_semver` module to find it + if best_version := nodesemver.max_satisfying(group, constraint): + best_versions.append(str(best_version)) + + # Return all best versions + return best_versions def find_best_solc_version(input_file) -> Optional[str]: """Find the best version of Solc compiler for a smart contract. This version @@ -68,3 +91,12 @@ def find_best_solc_version(input_file) -> Optional[str]: pragmas.""" pragma_versions = find_pragma_solc_version(input_file) return find_best_solc_version_for_pragma(pragma_versions) + + +def find_all_best_solc_versions(input_file) -> List[str]: + """Find multiple best versions of Solc compiler for a smart contract. These + versions are the latest patches of each version satisfying the required + pragmas. + """ + pragma_versions = find_pragma_solc_version(input_file) + return find_all_best_solc_versions(pragma_versions)