+ {#- SIDE NAV, TOGGLES ON MOBILE #}
+
+
+
+
+ {#- MOBILE NAV, TRIGGLES SIDE NAV ON TOGGLE #}
+ {#- Translators: This is an ARIA section label for the navigation menu that is visible when viewing the page on mobile devices -#}
+
+
+
\ No newline at end of file
diff --git a/docs/conf.py b/docs/conf.py
index 0856139..5d29ccd 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,89 +1,60 @@
-#!/usr/bin/python3
-
-from pathlib import Path
-from typing import Dict, List
-
-# -*- coding: utf-8 -*-
#
# Configuration file for the Sphinx documentation builder.
#
# This file does only contain a selection of the most common options. For a
# full list see the documentation:
-# http://www.sphinx-doc.org/en/master/config
-
+# https://www.sphinx-doc.org/en/master/config
# -- Path setup --------------------------------------------------------------
-
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
-# import os
-# import sys
-# sys.path.insert(0, os.path.abspath('.'))
-
-
-def setup(sphinx):
- pass
-
+import os
+import re
+import sys
+from functools import lru_cache
+from pathlib import Path
+from typing import List
-with Path(__file__).parent.joinpath("../setup.py").open() as fp:
- for line in fp:
- if "version=" in line:
- setup_version = line.split('"')[1]
- break
+import requests
+from packaging.version import Version
+sys.path.insert(0, os.path.abspath(".."))
# -- Project information -----------------------------------------------------
-
project = "py-solc-x"
-copyright = "2020"
-author = "Ben Hauser"
-
-# The short X.Y version
-version = setup_version
-# The full version, including alpha/beta/rc tags
-release = setup_version
-
-
-# -- General configuration ---------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-#
-# needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be
-# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
-# ones.
-extensions: List = ["sphinx.ext.intersphinx"]
+copyright = "2023, ApeWorX LTD"
+author = "ApeWorX Team"
+extensions = [
+ "myst_parser",
+ "sphinx_click",
+ "sphinx.ext.autodoc",
+ "sphinx.ext.autosummary",
+ "sphinx.ext.napoleon",
+ "sphinx_rtd_theme",
+ "sphinx_plausible",
+]
+autosummary_generate = True
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
-# The suffix(es) of source filenames.
-# You can specify multiple suffix as a list of string:
-#
-# source_suffix = ['.rst', '.md']
-source_suffix = ".rst"
-
-# The master toctree document.
-master_doc = "toctree"
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#
-# This is also used if you do content translation via gettext catalogs.
-# Usually you set "language" from the command line for these cases.
-language = None
-
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
-exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
+exclude_patterns: List[str] = ["_build", ".DS_Store"]
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = "sphinx"
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+source_suffix = [".rst", ".md"]
+
+# The master toctree document.
+master_doc = "index"
+
+# Configure Pluasible
+plausible_domain = "docs.apeworx.io"
# -- Options for HTML output -------------------------------------------------
@@ -91,105 +62,54 @@ def setup(sphinx):
# a list of builtin themes.
#
html_theme = "sphinx_rtd_theme"
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-#
-# html_theme_options = {}
+html_favicon = "favicon.ico"
+html_logo = "logo.gif"
+html_baseurl = "/py-solc-x/"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]
-html_css_files = ["css/toggle.css", "css/dark.css"]
+# These paths are either relative to html_static_path
+# or fully qualified paths (eg. https://...)
+html_css_files = ["custom.css"]
-html_js_files = ["js/toggle.js"]
+# Currently required for how we handle method docs links in the Myst parser
+# since not all links are available in the markdown files pre-build.
+myst_all_links_external = True
-# Custom sidebar templates, must be a dictionary that maps document names
-# to template names.
-#
-# The default sidebars (for documents that don't match any pattern) are
-# defined by theme itself. Builtin themes are using these templates by
-# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
-# 'searchbox.html']``.
-#
-# html_sidebars = {}
-
-
-# -- Options for HTMLHelp output ---------------------------------------------
-# Output file base name for HTML help builder.
-htmlhelp_basename = "Browniedoc"
+def fixpath(path: str) -> str:
+ """
+ Change paths to reference the resources from 'latest/' to save room.
+ """
+ suffix = path.split("_static")[1]
+ new = f"/{project}/latest/_static"
+ if suffix:
+ new = str(Path(new) / suffix.lstrip("/"))
-# -- Options for LaTeX output ------------------------------------------------
-
-latex_elements: Dict = {
- # The paper size ('letterpaper' or 'a4paper').
- #
- # 'papersize': 'letterpaper',
- # The font size ('10pt', '11pt' or '12pt').
- #
- # 'pointsize': '10pt',
- # Additional stuff for the LaTeX preamble.
- #
- # 'preamble': '',
- # Latex figure (float) alignment
- #
- # 'figure_align': 'htbp',
-}
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title,
-# author, documentclass [howto, manual, or own class]).
-latex_documents = [(master_doc, "solcx.tex", "py-solc-x Documentation", "Ben Hauser", "manual")]
+ return new
-# -- Options for manual page output ------------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [(master_doc, "solcx", "py-solc-x Documentation", [author], 1)]
-
-
-# -- Options for Texinfo output ----------------------------------------------
-
-# Grouping the document tree into Texinfo files. List of tuples
-# (source start file, target name, title, author,
-# dir menu entry, description, category)
-texinfo_documents = [
- (
- master_doc,
- "py-solc-x",
- "py-solc-x Documentation",
- author,
- "py-solc-x",
- "Python wrapper and version management tool for the solc Solidity compiler.",
- "py-solc-x",
- )
-]
-
-
-# -- Options for Epub output -------------------------------------------------
-
-# Bibliographic Dublin Core info.
-epub_title = project
-
-# The unique identifier of the text. This can be a ISBN number
-# or the project homepage.
-#
-# epub_identifier = ''
-
-# A unique identification for the text.
-#
-# epub_uid = ''
+@lru_cache(maxsize=None)
+def get_versions() -> List[str]:
+ """
+ Get all the versions from the Web.
+ """
+ api_url = "https://api.github.com/repos/ApeWorx/py-solc-x/git/trees/gh-pages?recursive=1"
+ response = requests.get(api_url)
+ response.raise_for_status()
+ pattern = re.compile(r"v\d+.?\d+.?\d+$")
+ data = response.json()
+ tree = data.get("tree", [])
+ versions = list({x["path"] for x in tree if x["type"] == "tree" and pattern.match(x["path"])})
+ sorted_version_objs = sorted([Version(v.lstrip("v")) for v in versions], reverse=True)
+ return [f"v{x}" for x in sorted_version_objs]
-# A list of files that should not be packed into the epub file.
-epub_exclude_files = ["search.html"]
-intersphinx_mapping = {
- "python": ("https://docs.python.org/3.8/", None),
- "semantic_version": ("https://python-semanticversion.readthedocs.io/en/latest/", None),
+html_context = {
+ "fixpath": fixpath,
+ "get_versions": get_versions,
}
diff --git a/docs/favicon.ico b/docs/favicon.ico
new file mode 100644
index 0000000..05f17aa
Binary files /dev/null and b/docs/favicon.ico differ
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..933ee11
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,22 @@
+# Python Solc-X Docs
+
+```{eval-rst}
+.. toctree::
+ :caption: User Guides
+ :maxdepth: 1
+
+ userguides/quickstart
+ userguides/using-the-compiler
+ userguides/version-management
+```
+
+```{eval-rst}
+.. toctree::
+ :caption: Python Reference
+ :maxdepth: 1
+
+ methoddocs/exceptions.md
+ methoddocs/install.md
+ methoddocs/main.md
+ methoddocs/wrapper.md
+```
diff --git a/docs/index.rst b/docs/index.rst
deleted file mode 100644
index fbb8e22..0000000
--- a/docs/index.rst
+++ /dev/null
@@ -1,22 +0,0 @@
-=========
-py-solc-x
-=========
-
-Python wrapper and version management tool for the ``solc`` `Solidity `_ compiler.
-
-Features
-========
-
-* Full support for Solidity versions ``>=0.4.11``
-* Installs Solidity on Linux, OSX and Windows
-* Compiles Solidity from source on Linux and OSX
-
-Credit
-======
-
-`py-solc-x `_ is forked from `py-solc `_ which was written by `Piper Merriam `_.
-
-Dependencies
-============
-
-Py-solc-x allows the use of multiple versions of solc, and can install or compile them as needed. If you wish to compile from source you must first install the required `solc dependencies `_.
diff --git a/docs/logo.gif b/docs/logo.gif
new file mode 100644
index 0000000..b3a1bcc
Binary files /dev/null and b/docs/logo.gif differ
diff --git a/docs/methoddocs/exceptions.md b/docs/methoddocs/exceptions.md
new file mode 100644
index 0000000..e6f2850
--- /dev/null
+++ b/docs/methoddocs/exceptions.md
@@ -0,0 +1,7 @@
+# Exceptions
+
+```{eval-rst}
+.. automodule:: solcx.exceptions
+ :members:
+ :show-inheritance:
+```
diff --git a/docs/methoddocs/install.md b/docs/methoddocs/install.md
new file mode 100644
index 0000000..0b56954
--- /dev/null
+++ b/docs/methoddocs/install.md
@@ -0,0 +1,7 @@
+# Install
+
+```{eval-rst}
+.. automodule:: solcx.install
+ :members:
+ :show-inheritance:
+```
diff --git a/docs/methoddocs/main.md b/docs/methoddocs/main.md
new file mode 100644
index 0000000..e41fbfb
--- /dev/null
+++ b/docs/methoddocs/main.md
@@ -0,0 +1,7 @@
+# Main
+
+```{eval-rst}
+.. automodule:: solcx.main
+ :members:
+ :show-inheritance:
+```
diff --git a/docs/methoddocs/wrapper.md b/docs/methoddocs/wrapper.md
new file mode 100644
index 0000000..f9bb5df
--- /dev/null
+++ b/docs/methoddocs/wrapper.md
@@ -0,0 +1,7 @@
+# Wrapper
+
+```{eval-rst}
+.. automodule:: solcx.wrapper
+ :members:
+ :show-inheritance:
+```
diff --git a/docs/solc-wrapper.rst b/docs/solc-wrapper.rst
deleted file mode 100644
index 10bcf05..0000000
--- a/docs/solc-wrapper.rst
+++ /dev/null
@@ -1,34 +0,0 @@
-=============================
-The Low-Level Process Wrapper
-=============================
-
-Along with the :ref:`main compiler functions `, you can also directly call ``solc`` using the low-level wrapper.
-
-.. py:function:: solc_wrapper(solc_binary=None, stdin=None, source_files=None, import_remappings=None, success_return_code=None, **kwargs)
-
- Wrapper function for calling to ``solc``.
-
- Returns the process ``stdout`` as a string, ``stderr`` as a string, the full command executed as a list of strings, and the completed :py:class:`Popen ` object used to call ``solc``.
-
- **Arguments**
-
- ``solc_binary`` : Path | str
- Location of the ``solc`` binary. If not given, the current default binary is used.
- ``stdin`` : str
- Input to pass to ``solc`` via stdin
- ``source_files`` List | Path | str
- Solidity source file, or list of source files, to be compiled. Files may be given as strings or :py:class:`Path ` objects.
- ``import_remappings`` : Dict | List | str
- Path remappings. May be given as a string or list of strings formatted as ``"prefix=path"``
- or a dict of ``{"prefix": "path"}``
- ``success_return_code`` : int
- Expected exit code. Raises ``SolcError`` if the process returns a different value. Defaults to ``0``.
- ``**kwargs`` Any
- Flags to be passed to `solc`. Keywords are converted to flags by prepending ``--`` and replacing ``_`` with ``-``, for example the keyword ``evm_version`` becomes ``--evm-version``. Values may be given in the following formats:
-
- * ``False`` or ``None``: The flag is ignored
- * ``True``: The flag is passed to the compiler without any arguments
- * ``str``: The value is given as an argument without any modification
- * ``int``: The value is converted to a string
- * ``Path``: The value is converted to a string via :py:meth:`Path.as_posix `
- * ``List`` or ``Tuple``: Elements in the sequence are converted to strings and joined with ``,``
diff --git a/docs/toctree.rst b/docs/toctree.rst
deleted file mode 100644
index ae76270..0000000
--- a/docs/toctree.rst
+++ /dev/null
@@ -1,11 +0,0 @@
-=======
-Brownie
-=======
-
-.. toctree::
- :maxdepth: 2
-
- Overview
- using-the-compiler.rst
- solc-wrapper.rst
- version-management.rst
diff --git a/docs/userguides/quickstart.md b/docs/userguides/quickstart.md
new file mode 100644
index 0000000..c7719d8
--- /dev/null
+++ b/docs/userguides/quickstart.md
@@ -0,0 +1,2 @@
+```{include} ../../README.md
+```
diff --git a/docs/userguides/using-the-compiler.md b/docs/userguides/using-the-compiler.md
new file mode 100644
index 0000000..e455859
--- /dev/null
+++ b/docs/userguides/using-the-compiler.md
@@ -0,0 +1,66 @@
+# Using the Compiler
+
+py-solc-x provides several functions that you can use to interact with the `solc` compiler.
+
+## Compiling a Source String
+
+Compile a Solidity contract.
+Compilation is handled via the `--combined-json` flag. Depending on the Solidity version used, some keyword arguments may not be available.
+Returns a dict, where each top-level key is a contract. The filename will be ``.
+
+```python
+import solcx
+
+solcx.compile_source(
+ "contract Foo { function bar() public { return; } }",
+ output_values=["abi", "bin-runtime"],
+ solc_version="0.7.0"
+)
+```
+
+## Compiling Files
+
+Compile one or more Solidity source files.
+Compilation is handled via the `--combined-json` flag.
+Depending on the Solidity version used, some keyword arguments may not be available.
+Returns a dict, where each top-level key is a contract.
+
+```python
+import solcx
+
+solcx.compile_files(
+ ["Foo.sol"],
+ output_values=["abi", "bin-runtime"],
+ solc_version="0.7.0"
+)
+```
+
+## Compiling with the Standard JSON Format
+
+Compile Solidity contracts using the JSON-input-output interface.
+See the Solidity documentation on [the compiler input-output JSON](https://solidity.readthedocs.io/en/latest/using-the-compiler.html#compiler-input-and-output-json-description) for details on the expected JSON input and output formats.
+
+```python
+import solcx
+
+solcx.compile_standard(
+ {},
+ solc_version="0.7.0"
+)
+```
+
+## Linking Libraries
+
+Add library addresses into unlinked bytecode.
+See the Solidity documentation on [using the commandline compiler](https://solidity.readthedocs.io/en/latest/using-the-compiler.html#commandline-compiler%3E) for more information on linking libraries.
+
+```python
+import solcx
+
+unlinked_bytecode = "606060405260768060106000396000f3606060405260e060020a6000350463e7f09e058114601a575b005b60187f0c55699c00000000000000000000000000000000000000000000000000000000606090815273__TestA_________________________________90630c55699c906064906000906004818660325a03f41560025750505056"
+
+solcx.link_code(
+ unlinked_bytecode,
+ {'TestA': "0xd3cda913deb6f67967b99d67acdfa1712c293601"}
+)
+```
diff --git a/docs/userguides/version-management.md b/docs/userguides/version-management.md
new file mode 100644
index 0000000..6545458
--- /dev/null
+++ b/docs/userguides/version-management.md
@@ -0,0 +1,114 @@
+# Solidity Version Management
+
+## Installation Folder
+
+By default, `solc` versions are installed at `~/.solcx/`.
+Each installed version is named using the following pattern: `solc-v[MAJOR].[MINOR].[PATH]`.
+
+If you wish to install to a different directory you can specify it with the `SOLCX_BINARY_PATH` environment variable.
+You can also give a custom directory to most installation functions using the optional `solcx_binary_path` keyword argument.
+
+```python
+import solcx
+solcx.get_solcx_install_folder()
+```
+
+## Getting and Setting the Active Version
+
+When py-solc-x is imported, it attempts to locate an installed version of `solc` using `which` on Linux or OSX systems, or `where.exe` on Windows.
+If found, this version is set as the active version.
+If not found, it uses the latest version that has been installed by py-solc-x.
+
+## Getting the Active Version
+
+Use the following methods to check the active `solc` version:
+
+```python
+import solcx
+
+solcx.get_solc_version()
+solcx.get_solc_version(with_commit_hash=True)
+
+# Also, get the path to the executable:
+solcx.install.get_executable()
+```
+
+## Setting the Active Version
+
+Set the currently active `solc` version:
+
+```python
+import solcx
+
+solcx.set_solc_version('0.5.0')
+```
+
+Set the currently active `solc` binary based on a pragma statement.
+The newest installed version that matches the pragma is chosen.
+
+```python
+import solcx
+
+solcx.set_solc_version_pragma('pragma solidity ^0.5.0;')
+```
+
+## Importing Already-Installed Versions
+
+Search for and copy installed `solc` versions into the local installation folder.
+This function is especially useful on OSX, to access Solidity versions that you have installed from homebrew and where a precompiled binary is not available.
+
+```python
+import solcx
+
+solcx.import_installed_solc()
+```
+
+## Installing Solidity
+
+py-solc-x downloads and installs precompiled binaries from [solc-bin.ethereum.org](solc-bin.ethereum.org).
+Different binaries are available depending on your operating system.
+
+## Getting Installable Versions
+
+```python
+import solcx
+
+solcx.get_installable_solc_versions()
+```
+
+## Installing Precompiled Binaries
+
+Download and install a precompiled `solc` binary:
+
+```python
+import solcx
+
+solcx.install_solc(version="latest", show_progress=False, solcx_binary_path=None)
+```
+
+## Building from Source
+
+When a precompiled version of Solidity isn't available for your operating system, you may still install it by building from the source code.
+Source code is downloaded from [GitHub](https://github.com/ethereum/solidity/releases).
+
+**NOTE**: If you wish to compile from source you must first install the required [solc dependencies](https://solidity.readthedocs.io/en/latest/installing-solidity.html#building-from-source).
+
+## Getting Compilable Versions
+
+Return a list of all `solc` versions that can be installed by py-solc-x.
+
+```python
+import solcx
+
+solcx.get_compilable_solc_versions()
+```
+
+## Compiling Solidity from Source
+
+Install a version of `solc` by downloading and compiling source code.
+
+```python
+import solcx
+
+solcx.compile_solc("0.8.17", show_progress=False, solcx_binary_path=None)
+```
diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst
deleted file mode 100644
index 4d212e6..0000000
--- a/docs/using-the-compiler.rst
+++ /dev/null
@@ -1,245 +0,0 @@
-.. _using-the-compiler:
-
-==================
-Using the Compiler
-==================
-
-py-solc-x provides several functions that you can use to interact with the ``solc`` compiler.
-
-Compiling a Source String
-=========================
-
-.. py:function:: solcx.compile_source(source, **kwargs)
-
- Compile a Solidity contract.
-
- Compilation is handled via the ``--combined-json`` flag. Depending on the Solidity version used, some keyword arguments may not be available.
-
- Returns a dict, where each top-level key is a contract. The filename will be ````.
-
- .. code-block:: python
-
- >>> import solcx
- >>> solcx.compile_source(
- ... "contract Foo { function bar() public { return; } }",
- ... output_values=["abi", "bin-runtime"],
- ... solc_version="0.7.0"
- ... )
- {
- ':Foo': {
- 'abi': [{'inputs': [], 'name': 'bar', 'outputs': [], 'stateMutability': 'nonpayable', 'type': 'function'}],
- 'bin-runtime': '6080604052348015600f57600080fd5b506004361060285760003560e01c8063febb0f7e14602d575b600080fd5b60336035565b005b56fea26469706673582212203cfdbce82ee8eab351107edac2ebb9dbe5c1aa8bd26609b0eedaa105ed3d4dce64736f6c63430007000033'
- }
- }
-
- **Required Arguments**
-
- ``source`` str
- Solidity contract to be compiled.
-
- **Optional py-solc-x Arguments**
-
- ``solc_binary`` str | Path
- Path of the ``solc`` binary to use. May be given as a string or :py:class:`Path ` object. If not given, the currently active version is used (as set by :func:`solcx.set_solc_version `)
- ``solc_version`` str | Version
- ``solc`` version to use. May be given as a string or :py:class:`Version ` object. If not given, the currently active version is used. Ignored if ``solc_binary`` is also given.
- ``allow_empty`` bool
- If ``True``, do not raise when no compiled contracts are returned. Defaults to ``False``.
-
- **Optional Compiler Arguments**
-
- Depending on the Solidity version used, using some of these arguments may raise ``UnknownOption``. See the documentation for your target Solidity version for more information.
-
- ``output_values`` List
- Compiler outputs to return. Valid options depend on the version of ``solc``.
- If not given, all possible outputs for the active version are returned.
- ``import_remappings`` Dict | List | str
- Path remappings. May be given as a string or list of strings formatted as
- ``"prefix=path"``, or a dict of ``{"prefix": "path"}``.
- ``base_path`` Path | str
- Use the given path as the root of the source tree instead of the root
- of the filesystem.
- ``allow_paths`` List | Path | str
- A path, or list of paths, to allow for imports.
- ``output_dir`` str
- Creates one file per component and contract/file at the specified directory.
- ``overwrite`` bool
- Overwrite existing files (used in combination with ``output_dir``)
- ``evm_version`` str
- Select the desired EVM version. Valid options depend on the ``solc`` version.
- ``revert_strings`` List | str
- Strip revert (and require) reason strings or add additional debugging
- information.
- ``metadata_hash`` str
- Choose hash method for the bytecode metadata or disable it.
- ``metadata_literal`` bool
- Store referenced sources as literal data in the metadata output.
- ``optimize`` bool
- Enable bytecode optimizer.
- ``optimize_runs`` int
- Set for how many contract runs to optimize. Lower values will optimize
- more for initial deployment cost, higher values will optimize more for
- high-frequency usage.
- ``optimize_yul`` bool
- Enable the yul optimizer.
- ``no_optimize_yul`` bool
- Disable the yul optimizer.
- ``yul_optimizations`` int
- Force yul optimizer to use the specified sequence of optimization steps
- instead of the built-in one.
-
-Compiling Files
-===============
-
-.. py:function:: solcx.compile_files(source, **kwargs)
-
- Compile one or more Solidity source files.
-
- Compilation is handled via the ``--combined-json`` flag. Depending on the Solidity version used, some keyword arguments may not be available.
-
- Returns a dict, where each top-level key is a contract.
-
- .. code-block:: python
-
- >>> import solcx
- >>> solcx.compile_files(
- ... ["Foo.sol"],
- ... output_values=["abi", "bin-runtime"],
- ... solc_version="0.7.0"
- ... )
- {
- ':Foo': {
- 'abi': [{'inputs': [], 'name': 'bar', 'outputs': [], 'stateMutability': 'nonpayable', 'type': 'function'}],
- 'bin-runtime': '6080604052348015600f57600080fd5b506004361060285760003560e01c8063febb0f7e14602d575b600080fd5b60336035565b005b56fea26469706673582212203cfdbce82ee8eab351107edac2ebb9dbe5c1aa8bd26609b0eedaa105ed3d4dce64736f6c63430007000033'
- }
- }
-
- **Required Arguments**
-
- ``source_files`` List | Path | str
- Solidity source file, or list of source files, to be compiled. Files may be given as strings or :py:class:`Path ` objects.
-
- **Optional py-solc-x Arguments**
-
- ``solc_binary`` str | Path
- Path of the ``solc`` binary to use. May be given as a string or :py:class:`Path ` object. If not given, the currently active version is used (as set by :func:`solcx.set_solc_version `)
- ``solc_version`` str | Version
- ``solc`` version to use. May be given as a string or :py:class:`Version ` object. If not given, the currently active version is used. Ignored if ``solc_binary`` is also given.
- ``allow_empty`` bool
- If ``True``, do not raise when no compiled contracts are returned. Defaults to ``False``.
-
- **Optional Compiler Arguments**
-
- Depending on the Solidity version used, using some of these arguments may raise ``UnknownOption``. See the documentation for your target Solidity version for more information.
-
- ``output_values`` List
- Compiler outputs to return. Valid options depend on the version of ``solc``.
- If not given, all possible outputs for the active version are returned.
- ``import_remappings`` Dict | List | str
- Path remappings. May be given as a string or list of strings formatted as
- ``"prefix=path"``, or a dict of ``{"prefix": "path"}``.
- ``base_path`` Path | str
- Use the given path as the root of the source tree instead of the root
- of the filesystem.
- ``allow_paths`` List | Path | str
- A path, or list of paths, to allow for imports.
- ``output_dir`` str
- Creates one file per component and contract/file at the specified directory.
- ``overwrite`` bool
- Overwrite existing files (used in combination with ``output_dir``)
- ``evm_version`` str
- Select the desired EVM version. Valid options depend on the ``solc`` version.
- ``revert_strings`` List | str
- Strip revert (and require) reason strings or add additional debugging
- information.
- ``metadata_hash`` str
- Choose hash method for the bytecode metadata or disable it.
- ``metadata_literal`` bool
- Store referenced sources as literal data in the metadata output.
- ``optimize`` bool
- Enable bytecode optimizer.
- ``optimize_runs`` int
- Set for how many contract runs to optimize. Lower values will optimize
- more for initial deployment cost, higher values will optimize more for
- high-frequency usage.
- ``optimize_yul`` bool
- Enable the yul optimizer.
- ``no_optimize_yul`` bool
- Disable the yul optimizer.
- ``yul_optimizations`` int
- Force yul optimizer to use the specified sequence of optimization steps
- instead of the built-in one.
-
-Compiling with the Standard JSON Format
-=======================================
-
-.. py:function:: solcx.compile_standard(input_data, **kwargs)
-
- Compile Solidity contracts using the JSON-input-output interface.
-
- See the Solidity documentation on `the compiler input-output JSON `_ for details on the expected JSON input and output formats.
-
- **Required Arguments**
-
- ``input_data`` Dict
- Compiler JSON input.
-
- **Optional py-solc-x Arguments**
-
- ``solc_binary`` str | Path
- Path of the ``solc`` binary to use. May be given as a string or :py:class:`Path ` object. If not given, the currently active version is used (as set by :func:`solcx.set_solc_version `)
- ``solc_version`` str | Version
- ``solc`` version to use. May be given as a string or :py:class:`Version ` object. If not given, the currently active version is used. Ignored if ``solc_binary`` is also given.
- ``allow_empty`` bool
- If ``True``, do not raise when no compiled contracts are returned. Defaults to ``False``.
-
- **Optional Compiler Arguments**
-
- Depending on the Solidity version used, using some of these arguments may raise ``UnknownOption``. See the documentation for your target Solidity version for more information.
-
- ``base_path`` Path | str
- Use the given path as the root of the source tree instead of the root
- of the filesystem.
- ``allow_paths`` List | Path | str
- A path, or list of paths, to allow for imports.
- ``output_dir`` str
- Creates one file per component and contract/file at the specified directory.
- ``overwrite`` bool
- Overwrite existing files (used in combination with ``output_dir``)
-
-Linking Libraries
-=================
-
-.. py:function:: solcx.link_code(unlinked_bytecode, libraries, solc_binary=None, solc_version=None)
-
- Add library addresses into unlinked bytecode.
-
- See the Solidity documentation on `using the commandline compiler `_ for more information on linking libraries.
-
- Returns the linked bytecode as a string.
-
- .. code-block:: python
-
- >>> import solcx
- >>> unlinked_bytecode = "606060405260768060106000396000f3606060405260e060020a6000350463e7f09e058114601a575b005b60187f0c55699c00000000000000000000000000000000000000000000000000000000606090815273__TestA_________________________________90630c55699c906064906000906004818660325a03f41560025750505056"
-
- >>> solcx.link_code(
- ... unlinked_bytecode,
- ... {'TestA': "0xd3cda913deb6f67967b99d67acdfa1712c293601"}
- ... )
- "606060405260768060106000396000f3606060405260e060020a6000350463e7f09e058114601a575b005b60187f0c55699c00000000000000000000000000000000000000000000000000000000606090815273d3cda913deb6f67967b99d67acdfa1712c29360190630c55699c906064906000906004818660325a03f41560025750505056"
-
-
- **Required Arguments**
-
- ``unlinked_bytecode`` str
- Compiled bytecode containing one or more library placeholders.
- ``libraries`` Dict
- Library addresses given as ``{"library name": "address"}``
-
- **Optional py-solc-x Arguments**
-
- ``solc_binary`` str | Path
- Path of the ``solc`` binary to use. May be given as a string or :py:class:`Path ` object. If not given, the currently active version is used (as set by :func:`solcx.set_solc_version `)
- ``solc_version`` str | Version
- ``solc`` version to use. May be given as a string or :py:class:`Version ` object. If not given, the currently active version is used. Ignored if ``solc_binary`` is also given.
diff --git a/docs/version-management.rst b/docs/version-management.rst
deleted file mode 100644
index 523e579..0000000
--- a/docs/version-management.rst
+++ /dev/null
@@ -1,183 +0,0 @@
-===========================
-Solidity Version Management
-===========================
-
-Installation Folder
-===================
-
-By default, ``solc`` versions are installed at ``~/.solcx/``. Each installed version is named using the following pattern: ``solc-v[MAJOR].[MINOR].[PATH]``
-
-If you wish to install to a different directory you can specify it with the ``SOLCX_BINARY_PATH`` environment variable. You can also give a custom directory to most installation functions using the optional ``solcx_binary_path`` keyword argument.
-
-.. py:function:: solcx.get_solcx_install_folder(solcx_binary_path=None)
-
- Return the directory where py-solc-x stores installed ``solc`` binaries.
-
- .. code-block:: python
-
- >>> solcx.get_solcx_install_folder()
- PosixPath('/home/computer/.solcx')
-
-Getting and Setting the Active Version
-======================================
-
-When py-solc-x is imported, it attempts to locate an installed version of ``solc`` using ``which`` on Linux or OSX systems, or ``where.exe`` on Windows. If found, this version is set as the active version. If not found, it uses the latest version that has been installed by py-solc-x.
-
-
-Getting the Active Version
---------------------------
-
-Use the following methods to check the active ``solc`` version:
-
-.. py:function:: solcx.get_solc_version(with_commit_hash=False)
-
- Return the version of the current active ``solc`` binary, as a :py:class:`Version ` object.
-
- * ``with_commit_hash``: If ``True``, the returned version includes the commit hash
-
- .. code-block:: python
-
- >>> solcx.get_solc_version()
- Version('0.7.0')
-
- >>> solcx.get_solc_version(True)
- Version('0.7.0+commit.9e61f92b')
-
-
-.. py:function:: solcx.install.get_executable(version=None, solcx_binary_path=None)
-
- Return a :py:class:`Path ` object for a ``solc`` binary.
-
- If no arguments are given, returns the current active version. If a version is specified, returns the installed binary matching the given version.
-
- Raises ``SolcNotInstalled`` if no binary is found.
-
- .. code-block:: python
-
- >>> solcx.install.get_executable()
- PosixPath('/usr/bin/solc')
-
-.. py:function:: solcx.get_installed_solc_versions(solcx_binary_path=None)
-
- Return a list of currently installed ``solc`` versions.
-
- .. code-block:: python
-
- >>> solcx.get_installed_solc_versions()
- [Version('0.7.0'), Version('0.6.8'), Version('0.6.3'), Version('0.5.7'), Version('0.4.25')]
-
-Setting the Active Version
---------------------------
-
-.. py:function:: solcx.set_solc_version(version, silent=False, solcx_binary_path=None)
-
- Set the currently active ``solc`` version.
-
- .. code-block:: python
-
- >>> solcx.set_solc_version('0.5.0')
-
-.. py:function:: solcx.set_solc_version_pragma(pragma_string, silent=False, check_new=False)
-
- Set the currently active ``solc`` binary based on a pragma statement.
-
- The newest installed version that matches the pragma is chosen. Raises ``SolcNotInstalled`` if no installed versions match.
-
- .. code-block:: python
-
- >>> solcx.set_solc_version_pragma('pragma solidity ^0.5.0;')
- Version('0.5.17')
-
-
-Importing Already-Installed Versions
-====================================
-
-.. py:function:: solcx.import_installed_solc(solcx_binary_path=None)
-
- Search for and copy installed ``solc`` versions into the local installation folder.
-
- This function is especially useful on OSX, to access Solidity versions that you have installed from homebrew and where a precompiled binary is not available.
-
- .. code-block:: python
-
- >>> solcx.import_installed_solc()
- [Version('0.7.0'), Version('0.6.12')]
-
-
-Installing Solidity
-===================
-
-py-solc-x downloads and installs precompiled binaries from `solc-bin.ethereum.org `_. Different binaries are available depending on your operating system.
-
-Getting Installable Versions
-----------------------------
-
-.. py:function:: solcx.get_installable_solc_versions()
-
- Return a list of all ``solc`` versions that can be installed by py-solc-x.
-
-
- .. code-block:: python
-
- >>> solcx.get_installable_solc_versions()
- [Version('0.7.0'), Version('0.6.12'), Version('0.6.11'), Version('0.6.10'), Version('0.6.9'), Version('0.6.8'), Version('0.6.7'), Version('0.6.6'), Version('0.6.5'), Version('0.6.4'), Version('0.6.3'), Version('0.6.2'), Version('0.6.1'), Version('0.6.0'), Version('0.5.17'), Version('0.5.16'), Version('0.5.15'), Version('0.5.14'), Version('0.5.13'), Version('0.5.12'), Version('0.5.11'), Version('0.5.10'), Version('0.5.9'), Version('0.5.8'), Version('0.5.7'), Version('0.5.6'), Version('0.5.5'), Version('0.5.4'), Version('0.5.3'), Version('0.5.2'), Version('0.5.1'), Version('0.5.0'), Version('0.4.26'), Version('0.4.25'), Version('0.4.24'), Version('0.4.23'), Version('0.4.22'), Version('0.4.21'), Version('0.4.20'), Version('0.4.19'), Version('0.4.18'), Version('0.4.17'), Version('0.4.16'), Version('0.4.15'), Version('0.4.14'), Version('0.4.13'), Version('0.4.12'), Version('0.4.11')]
-
-Installing Precompiled Binaries
--------------------------------
-
-.. py:function:: solcx.install_solc(version="latest", show_progress=False, solcx_binary_path=None)
-
- Download and install a precompiled ``solc`` binary.
-
- ``version`` str | Version
- Version of ``solc`` to install. Default is the newest available version.
- ``show_progress`` bool
- If ``True``, display a progress bar while downloading. Requires installing
- the `tqdm `_ package.
- ``solcx_binary_path`` Path | str
- User-defined path, used to override the default installation directory.
-
-Building from Source
-====================
-
-When a precompiled version of Solidity isn't available for your operating system, you may still install it by building from the source code. Source code is downloaded from `Github `_.
-
-.. note::
-
- If you wish to compile from source you must first install the required `solc dependencies `_.
-
-
-Getting Compilable Versions
----------------------------
-
-.. py:function:: solcx.get_compilable_solc_versions(headers=None)
-
- Return a list of all ``solc`` versions that can be installed by py-solc-x.
-
- ``headers`` Dict
- Headers to include in the request to Github.
-
- .. code-block:: python
-
- >>> solcx.get_compilable_solc_versions()
- [Version('0.7.0'), Version('0.6.12'), Version('0.6.11'), Version('0.6.10'), Version('0.6.9'), Version('0.6.8'), Version('0.6.7'), Version('0.6.6'), Version('0.6.5'), Version('0.6.4'), Version('0.6.3'), Version('0.6.2'), Version('0.6.1'), Version('0.6.0'), Version('0.5.17'), Version('0.5.16'), Version('0.5.15'), Version('0.5.14'), Version('0.5.13'), Version('0.5.12'), Version('0.5.11'), Version('0.5.10'), Version('0.5.9'), Version('0.5.8'), Version('0.5.7'), Version('0.5.6'), Version('0.5.5'), Version('0.5.4'), Version('0.5.3'), Version('0.5.2'), Version('0.5.1'), Version('0.5.0'), Version('0.4.26'), Version('0.4.25'), Version('0.4.24'), Version('0.4.23'), Version('0.4.22'), Version('0.4.21'), Version('0.4.20'), Version('0.4.19'), Version('0.4.18'), Version('0.4.17'), Version('0.4.16'), Version('0.4.15'), Version('0.4.14'), Version('0.4.13'), Version('0.4.12'), Version('0.4.11')]
-
-
-Compiling Solidity from Source
-------------------------------
-
-.. py:function:: solcx.compile_solc(version, show_progress=False, solcx_binary_path=None)
-
- Install a version of ``solc`` by downloading and compiling source code.
-
- This function is only available when using Linux or OSX.
-
- **Arguments:**
-
- ``version`` str | Version
- Version of ``solc`` to install.
- ``show_progress`` bool
- If ``True``, display a progress bar while downloading. Requires installing
- the `tqdm `_ package.
- ``solcx_binary_path`` Path | str
- User-defined path, used to override the default installation directory.
diff --git a/pyproject.toml b/pyproject.toml
index e4603ae..e633054 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,20 +1,39 @@
+[build-system]
+requires = ["setuptools>=51.1.1", "wheel", "setuptools_scm[toml]>=5.0"]
+
+[tool.mypy]
+exclude = "build/"
+check_untyped_defs = true
+
+[tool.setuptools_scm]
+write_to = "solcx/version.py"
+
+# NOTE: you have to use single-quoted strings in TOML for regular expressions.
+# It's the equivalent of r-strings in Python. Multiline strings are treated as
+# verbose regular expressions by Black. Use [ ] to denote a significant space
+# character.
+
[tool.black]
line-length = 100
-target-version = ['py36', 'py37', 'py38']
+target-version = ['py38', 'py39', 'py310', 'py311']
include = '\.pyi?$'
-exclude = '''
-/(
- \.eggs
- | \.git
- | \.hg
- | \.mypy_cache
- | \.tox
- | \.venv
- | _build
- | buck-out
- | build
- | dist
- | env
- | venv
-)/
-'''
+
+[tool.pytest.ini_options]
+addopts = """
+ -p no:ape_test
+ --cov-branch
+ --cov-report term
+ --cov-report html
+ --cov-report xml
+ --cov=ape_solidity
+"""
+python_files = "test_*.py"
+testpaths = "tests"
+markers = "fuzzing: Run Hypothesis fuzz test suite"
+
+[tool.isort]
+line_length = 100
+force_grid_wrap = 0
+include_trailing_comma = true
+multi_line_output = 3
+use_parentheses = true
diff --git a/requirements-dev.txt b/requirements-dev.txt
deleted file mode 100644
index 44a2214..0000000
--- a/requirements-dev.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-black==19.10b0
-bumpversion==0.5.3
-flake8==3.8.3
-isort==5.4.2
-mypy==0.782
-pytest-cov==2.10.1
-pytest-mock==3.6.1
-pytest>=6.0.0,<7.0.0
-requests>=2.19.0,<3
-semantic_version>=2.8.1,<3
-sphinx==3.2.1
-sphinx_rtd_theme==0.5.0
-tox==3.19.0
-tqdm>=4.48.0,<5.0.0
-twine==3.2.0
-wheel==0.35.1
diff --git a/setup.cfg b/setup.cfg
index bad57ff..1277c6b 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,26 +1,7 @@
-[bumpversion]
-current_version = 1.1.1
-
-[bumpversion:file:setup.py]
-
[flake8]
max-line-length = 100
-ignore = E203,W503
-per-file-ignores =
- */__init__.py: F401
-
-[mypy]
-ignore_missing_imports = True
-follow_imports = silent
-
-[tool:isort]
-force_grid_wrap = 0
-include_trailing_comma = True
-known_third_party = pytest,requests,semantic_version,setuptools
-line_length = 100
-multi_line_output = 3
-use_parentheses = True
-
-[tool:pytest]
-addopts = --cov=solcx --cov-branch --cov-report xml
-
+exclude =
+ venv*
+ docs
+ build
+ tests/node_modules
diff --git a/setup.py b/setup.py
index 517e031..33c40aa 100644
--- a/setup.py
+++ b/setup.py
@@ -1,32 +1,95 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
from setuptools import find_packages, setup
+extras_require = {
+ "test": [ # `test` GitHub Action jobs uses this
+ "pytest>=6.0", # Core testing package
+ "pytest-xdist", # multi-process runner
+ "pytest-cov", # Coverage analyzer plugin
+ "pytest-mock", # For using mocks
+ "hypothesis>=6.2.0,<7.0", # Strategy-based fuzzer
+ ],
+ "lint": [
+ "black>=23.10.1,<24", # auto-formatter and linter
+ "mypy>=1.6.1,<2", # Static type analyzer
+ "types-setuptools", # Needed due to mypy typeshed
+ "types-requests", # Needed due to mypy typeshed
+ "flake8>=6.1.0,<7", # Style linter
+ "isort>=5.10.1,<6", # Import sorting linter
+ "mdformat>=0.7.17", # Auto-formatter for markdown
+ "mdformat-gfm>=0.3.5", # Needed for formatting GitHub-flavored markdown
+ "mdformat-frontmatter>=0.4.1", # Needed for frontmatters-style headers in issue templates
+ ],
+ "doc": [
+ "myst-parser>=1.0.0,<2", # Parse markdown docs
+ "sphinx-click>=4.4.0,<5", # For documenting CLI
+ "Sphinx>=6.1.3,<7", # Documentation generator
+ "sphinx_rtd_theme>=1.2.0,<2", # Readthedocs.org theme
+ "sphinxcontrib-napoleon>=0.7", # Allow Google-style documentation
+ "sphinx-plausible>=0.1.2,<0.2",
+ ],
+ "release": [ # `release` GitHub Action job uses this
+ "setuptools", # Installation tool
+ "setuptools-scm", # Installation tool
+ "wheel", # Packaging tool
+ "twine", # Package upload tool
+ ],
+ "dev": [
+ "commitizen", # Manage commits and publishing releases
+ "pre-commit", # Ensure that linters are run prior to committing
+ "pytest-watch", # `ptw` test watcher/runner
+ "IPython", # Console for interacting
+ "ipdb", # Debugger (Must use `export PYTHONBREAKPOINT=ipdb.set_trace`)
+ ],
+}
+
+extras_require["dev"] = (
+ extras_require["test"]
+ + extras_require["lint"]
+ + extras_require["doc"]
+ + extras_require["release"]
+ + extras_require["dev"]
+)
+
+with open("./README.md") as readme:
+ long_description = readme.read()
+
setup(
name="py-solc-x",
- version="1.1.1", # don't change this manually, use bumpversion instead
+ use_scm_version=True,
+ setup_requires=["setuptools_scm"],
description="Python wrapper and version management tool for the solc Solidity compiler.",
- long_description_markdown_filename="README.md",
- author="Ben Hauser (forked from py-solc by Piper Merriam)",
- author_email="ben@hauser.id",
- url="https://github.com/iamdefinitelyahuman/py-solc-x",
+ long_description=long_description,
+ long_description_content_type="text/markdown",
+ author="ApeWorX Ltd.",
+ author_email="admin@apeworx.io",
+ url="https://github.com/ApeWorX/py-solc-x",
include_package_data=True,
+ python_requires=">=3.8,<4",
+ install_requires=[
+ "requests>=2.19.0,<3",
+ "packaging>=23.1,<24",
+ ],
+ extras_require=extras_require,
py_modules=["solcx"],
- setup_requires=["setuptools-markdown"],
- python_requires=">=3.6, <4",
- install_requires=["requests>=2.19.0,<3", "semantic_version>=2.8.1,<3"],
license="MIT",
zip_safe=False,
keywords="ethereum solidity solc",
packages=find_packages(exclude=["tests", "tests.*"]),
+ package_data={"solcx": ["py.typed"]},
classifiers=[
+ "Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Natural Language :: English",
+ "Operating System :: MacOS",
+ "Operating System :: POSIX",
"Programming Language :: Python :: 3",
- "Programming Language :: Python :: 3.6",
- "Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
],
)
diff --git a/solcx/__init__.py b/solcx/__init__.py
index 0e8284c..a409832 100644
--- a/solcx/__init__.py
+++ b/solcx/__init__.py
@@ -1,3 +1,4 @@
+from solcx import wrapper
from solcx.install import (
compile_solc,
get_compilable_solc_versions,
@@ -11,3 +12,22 @@
set_solc_version_pragma,
)
from solcx.main import compile_files, compile_source, compile_standard, get_solc_version, link_code
+
+__all__ = [
+ "compile_files",
+ "compile_solc",
+ "compile_source",
+ "compile_standard",
+ "get_compilable_solc_versions",
+ "get_installable_solc_versions",
+ "get_installed_solc_versions",
+ "get_solc_version",
+ "get_solcx_install_folder",
+ "import_installed_solc",
+ "install_solc",
+ "install_solc_pragma",
+ "link_code",
+ "set_solc_version",
+ "set_solc_version_pragma",
+ "wrapper",
+]
diff --git a/solcx/exceptions.py b/solcx/exceptions.py
index 0c8d53b..2baa954 100644
--- a/solcx/exceptions.py
+++ b/solcx/exceptions.py
@@ -1,4 +1,4 @@
-from typing import Dict, List
+from typing import Dict, List, Optional
class SolcError(Exception):
@@ -6,13 +6,13 @@ class SolcError(Exception):
def __init__(
self,
- message: str = None,
- command: List = None,
- return_code: int = None,
- stdin_data: str = None,
- stdout_data: str = None,
- stderr_data: str = None,
- error_dict: Dict = None,
+ message: Optional[str] = None,
+ command: Optional[List[str]] = None,
+ return_code: Optional[int] = None,
+ stdin_data: Optional[str] = None,
+ stdout_data: Optional[str] = None,
+ stderr_data: Optional[str] = None,
+ error_dict: Optional[Dict] = None,
) -> None:
if message is not None:
self.message = message
diff --git a/solcx/install.py b/solcx/install.py
index e95a408..b7fbeec 100644
--- a/solcx/install.py
+++ b/solcx/install.py
@@ -19,7 +19,8 @@
from typing import Dict, List, Optional, Union
import requests
-from semantic_version import SimpleSpec, Version
+from packaging.specifiers import SpecifierSet
+from packaging.version import InvalidVersion, Version
from solcx import wrapper
from solcx.exceptions import (
@@ -33,7 +34,7 @@
from solcx.utils.lock import get_process_lock
try:
- from tqdm import tqdm
+ from tqdm import tqdm # type: ignore[import-untyped]
except ImportError:
tqdm = None
@@ -65,7 +66,7 @@ def _convert_and_validate_version(version: Union[str, Version]) -> Version:
# validate the value, and return a Version object
if not isinstance(version, Version):
version = Version(version.lstrip("v"))
- if version not in SimpleSpec(">=0.4.11"):
+ if version not in SpecifierSet(">=0.4.11"):
raise UnsupportedVersionError("py-solc-x does not support solc versions <0.4.11")
return version
@@ -76,21 +77,18 @@ def _unlink_solc(solc_path: Path) -> None:
shutil.rmtree(solc_path.parent)
-def get_solcx_install_folder(solcx_binary_path: Union[Path, str] = None) -> Path:
+def get_solcx_install_folder(solcx_binary_path: Optional[Union[Path, str]] = None) -> Path:
"""
- Return the directory where `py-solc-x` stores installed `solc` binaries.
+ Return the directory where ``py-solc-x`` stores installed ``solc`` binaries.
- By default, this is `~/.solcx`
+ By default, this is ``~/.solcx``.
- Arguments
- ---------
- solcx_binary_path : Path | str, optional
- User-defined path, used to override the default installation directory.
+ Args:
+ solcx_binary_path (Optional[Union[Path, str]]): User-defined path, used
+ to override the default installation directory.
- Returns
- -------
- Path
- Subdirectory where `solc` binaries are are saved.
+ Returns:
+ Path: Subdirectory where ``solc`` binaries are are saved.
"""
if os.getenv(SOLCX_BINARY_PATH_VARIABLE):
return Path(os.environ[SOLCX_BINARY_PATH_VARIABLE])
@@ -104,30 +102,24 @@ def get_solcx_install_folder(solcx_binary_path: Union[Path, str] = None) -> Path
def _get_which_solc() -> Optional[Path]:
# get the path for the currently installed `solc` version, if any
- solc_path = shutil.which("solc")
- if solc_path is None:
- return None
- else:
- return Path(solc_path)
+ path = shutil.which("solc")
+ return Path(path) if path else None
-def import_installed_solc(solcx_binary_path: Union[Path, str] = None) -> List[Version]:
+def import_installed_solc(solcx_binary_path: Optional[Union[Path, str]] = None) -> List[Version]:
"""
- Search for and copy installed `solc` versions into the local installation folder.
+ Search for and copy installed ``solc`` versions into the local installation
+ folder.
- Arguments
- ---------
- solcx_binary_path : Path | str, optional
- User-defined path, used to override the default installation directory.
+ Args:
+ solcx_binary_path (Optional[Union[Path, str]]): User-defined path, used to
+ override the default installation directory.
- Returns
- -------
- List
- Imported solc versions
+ Returns:
+ List: Imported solc versions
"""
path_list = []
- solc_in_path = _get_which_solc()
- if solc_in_path:
+ if solc_in_path := _get_which_solc():
path_list.append(solc_in_path)
# on OSX, also copy all versions of solc from cellar
@@ -135,83 +127,97 @@ def import_installed_solc(solcx_binary_path: Union[Path, str] = None) -> List[Ve
path_list.extend(Path("/usr/local/Cellar").glob("solidity*/**/solc"))
imported_versions = []
+ solcx_binary_path = get_solcx_install_folder(solcx_binary_path=solcx_binary_path)
+ installed_versions = get_installed_solc_versions(solcx_binary_path=solcx_binary_path)
+
for path in path_list:
try:
version = wrapper.get_solc_version(path)
- assert version not in get_installed_solc_versions()
except Exception:
continue
- copy_path = get_solcx_install_folder(solcx_binary_path).joinpath(f"solc-v{version}")
+ if version in installed_versions:
+ # Already installed.
+ continue
+
+ base_path = get_solcx_install_folder(solcx_binary_path)
+ copy_path = base_path.joinpath(f"solc-v{version.base_version}")
if _get_os_name() == "windows":
copy_path.mkdir()
copy_path = copy_path.joinpath("solc.exe")
shutil.copy(path, copy_path)
+
try:
- # confirm that solc still works after being copied
- assert version == wrapper.get_solc_version(copy_path)
- imported_versions.append(version)
+ version_check = wrapper.get_solc_version(copy_path)
except Exception:
_unlink_solc(copy_path)
+ else:
+ if version != version_check:
+ _unlink_solc(copy_path)
+ else:
+ imported_versions.append(version)
+
return imported_versions
def get_executable(
- version: Union[str, Version] = None, solcx_binary_path: Union[Path, str] = None
+ version: Optional[Union[str, Version]] = None,
+ solcx_binary_path: Optional[Union[Path, str]] = None,
) -> Path:
"""
Return the Path to an installed `solc` binary.
- Arguments
- ---------
- version : str | Version, optional
- Installed `solc` version to get the path of. If not given, returns the
- path of the active version.
- solcx_binary_path : Path | str, optional
- User-defined path, used to override the default installation directory.
-
- Returns
- -------
- Path
- `solc` executable.
+ Args:
+ version (Optional[Union[str, Version]]): Installed ``solc`` version
+ to get the path of. If not given, returns the path of the active version.
+ solcx_binary_path (Optional[Union[Path, str]]): User-defined path, used to
+ override the default installation directory.
+
+ Returns:
+ Path: ``solc`` executable.
"""
if not version:
- if not _default_solc_binary:
- raise SolcNotInstalled(
- "Solc is not installed. Call solcx.get_installable_solc_versions()"
- " to view for available versions and solcx.install_solc() to install."
- )
- return _default_solc_binary
+ if binary := get_default_solc_binary():
+ return binary
+
+ raise SolcNotInstalled(
+ "Solc is not installed. Call solcx.get_installable_solc_versions()"
+ " to view for available versions and solcx.install_solc() to install."
+ )
version = _convert_and_validate_version(version)
- solc_bin = get_solcx_install_folder(solcx_binary_path).joinpath(f"solc-v{version}")
+ solc_bin = get_solcx_install_folder(solcx_binary_path).joinpath(f"solc-v{version.base_version}")
if _get_os_name() == "windows":
solc_bin = solc_bin.joinpath("solc.exe")
if not solc_bin.exists():
raise SolcNotInstalled(
- f"solc {version} has not been installed."
- f" Use solcx.install_solc('{version}') to install."
+ f"solc {version.base_version} has not been installed."
+ f" Use solcx.install_solc('{version.base_version}') to install."
)
return solc_bin
+def get_default_solc_binary():
+ return _default_solc_binary
+
+
def set_solc_version(
- version: Union[str, Version], silent: bool = False, solcx_binary_path: Union[Path, str] = None
+ version: Union[str, Version],
+ silent: bool = False,
+ solcx_binary_path: Optional[Union[Path, str]] = None,
) -> None:
"""
- Set the currently active `solc` binary.
-
- Arguments
- ---------
- version : str | Version, optional
- Installed `solc` version to get the path of. If not given, returns the
- path of the active version.
- silent : bool, optional
- If True, do not generate any logger output.
- solcx_binary_path : Path | str, optional
- User-defined path, used to override the default installation directory.
+ Set the currently active ``solc`` binary.
+
+ Args:
+ version (Union[str, Version]): Installed ``solc`` version
+ to get the path of. If not given, returns the path of the
+ active version.
+ silent (bool): If ``True``, do not generate any logger output.
+ solcx_binary_path (Optional[Union[Path, str]]): User-defined path,
+ used to override the default installation directory.
"""
version = _convert_and_validate_version(version)
global _default_solc_binary
@@ -222,12 +228,25 @@ def set_solc_version(
def _select_pragma_version(pragma_string: str, version_list: List[Version]) -> Optional[Version]:
comparator_set_range = pragma_string.replace(" ", "").split("||")
- comparator_regex = re.compile(r"(([<>]?=?|\^)\d+\.\d+\.\d+)+")
+ comparator_regex = re.compile(r"(([<>]?=?|\^)\d+\.\d+\.\d+)")
version = None
+ def _as_spec(item: str) -> str:
+ ret = item.replace("^", "~=")
+
+ if ret and ret[0].isnumeric():
+ return f"=={ret}"
+
+ elif ret and len(ret) >= 2 and ret[0] == "=" and ret[1] != "=":
+ return f"={ret}"
+
+ return ret
+
for comparator_set in comparator_set_range:
- spec = SimpleSpec(*(i[0] for i in comparator_regex.findall(comparator_set)))
- selected = spec.select(version_list)
+ specs = ",".join([_as_spec(i[0]) for i in comparator_regex.findall(comparator_set)])
+ spec = SpecifierSet(specs)
+ matching = sorted(list(spec.filter(version_list)), reverse=True)
+ selected = matching[0] if matching else None
if selected and (not version or version < selected):
version = selected
@@ -238,31 +257,28 @@ def set_solc_version_pragma(
pragma_string: str, silent: bool = False, check_new: bool = False
) -> Version:
"""
- Set the currently active `solc` binary based on a pragma statement.
-
- The newest installed version that matches the pragma is chosen. Raises
- `SolcNotInstalled` if no installed versions match.
-
- Arguments
- ---------
- pragma_string : str
- Pragma statement, e.g. "pragma solidity ^0.4.22;"
- silent : bool, optional
- If True, do not generate any logger output.
- check_new : bool, optional
- If True, also check if there is a newer compatible version that has not
- been installed.
-
- Returns
- -------
- Version
- The new active `solc` version.
+ Set the currently active ``solc`` binary based on a pragma statement.
+
+ The newest installed version that matches the pragma is chosen. =
+
+ Raises:
+ :class:`~solcx.exceptions.SolcNotInstalled`: When no installed versions match.
+
+ Args:
+ pragma_string (str): Pragma statement, e.g. ``"pragma solidity ^0.4.22;"``
+ silent (bool): If ``True``, do not generate any logger output. Defaults to
+ ``False``.
+ check_new (bool): If ``True``, also check if there is a newer compatible
+ version that has not been installed. Defaults to ``False``.
+
+ Returns:
+ Version: The new active `solc` version.
"""
- version = _select_pragma_version(pragma_string, get_installed_solc_versions())
- if version is None:
+ installed_versions = get_installed_solc_versions()
+ if not (version := _select_pragma_version(pragma_string, installed_versions)):
raise SolcNotInstalled(
f"No compatible solc version installed."
- f" Use solcx.install_solc_version_pragma('{version}') to install."
+ f" Use solcx.install_solc_version_pragma('{pragma_string}') to install."
)
set_solc_version(version, silent)
if check_new:
@@ -277,46 +293,44 @@ def install_solc_pragma(
pragma_string: str,
install: bool = True,
show_progress: bool = False,
- solcx_binary_path: Union[Path, str] = None,
+ solcx_binary_path: Optional[Union[Path, str]] = None,
) -> Version:
"""
- Find, and optionally install, the latest compatible `solc` version based on
- a pragma statement.
-
- Arguments
- ---------
- pragma_string : str
- Pragma statement, e.g. "pragma solidity ^0.4.22;"
- install : bool, optional
- If True, installs the version of `solc`.
- show_progress : bool, optional
- If True, display a progress bar while downloading. Requires installing
- the `tqdm` package.
- solcx_binary_path : Path | str, optional
- User-defined path, used to override the default installation directory.
-
- Returns
- -------
- Version
- Installed `solc` version.
+ Find, and optionally install, the latest compatible ``solc`` version
+ based on a pragma statement.
+
+ Args:
+ pragma_string (str): Pragma statement, e.g.
+ ``"pragma solidity ^0.4.22;"``.
+ install (bool): If ``True``, installs the version of ``solc``. Defaults
+ to ``True``.
+ show_progress (bool): If ``True``, display a progress bar while
+ downloading. Requires installing the ``tqdm`` package. Defaults to
+ ``False``.
+ solcx_binary_path (Optional[Union[Path, str]]): User-defined path,
+ used to override the default installation directory.
+
+ Returns:
+ Version: Installed ``solc`` version.
"""
- version = _select_pragma_version(pragma_string, get_installable_solc_versions())
- if not version:
- raise UnsupportedVersionError("Compatible solc version does not exist")
- if install:
+
+ installed_versions = get_installable_solc_versions()
+ if version := _select_pragma_version(pragma_string, installed_versions):
install_solc(version, show_progress=show_progress, solcx_binary_path=solcx_binary_path)
+ else:
+ raise UnsupportedVersionError(
+ f"Compatible solc version does not exist matching '{pragma_string}'."
+ )
return version
def get_installable_solc_versions() -> List[Version]:
"""
- Return a list of all `solc` versions that can be installed by py-solc-x.
+ Return a list of all ``solc`` versions that can be installed by py-solc-x.
- Returns
- -------
- List
- List of Versions objects of installable `solc` versions.
+ Returns:
+ List: List of Versions objects of installable ``solc`` versions.
"""
data = requests.get(BINARY_DOWNLOAD_BASE.format(_get_os_name(), "list.json"))
if data.status_code != 200:
@@ -330,17 +344,13 @@ def get_installable_solc_versions() -> List[Version]:
def get_compilable_solc_versions(headers: Optional[Dict] = None) -> List[Version]:
"""
- Return a list of all `solc` versions that can be compiled from source by py-solc-x.
+ Return a list of all ``solc`` versions that can be compiled from source by py-solc-x.
- Arguments
- ---------
- headers : Dict, optional
- Headers to include in the request to Github.
+ Args:
+ headers (Optional[Dict]): Headers to include in the request to Github.
- Returns
- -------
- List
- List of Versions objects of installable `solc` versions.
+ Returns:
+ List: List of Versions objects of installable `solc` versions.
"""
if _get_os_name() == "windows":
raise OSError("Compiling from source is not supported on Windows systems")
@@ -368,8 +378,8 @@ def get_compilable_solc_versions(headers: Optional[Dict] = None) -> List[Version
for release in data.json():
try:
- version = Version.coerce(release["tag_name"].lstrip("v"))
- except ValueError:
+ version = Version(release["tag_name"].lstrip("v"))
+ except InvalidVersion:
# ignore non-standard releases (e.g. the 0.8.x preview)
continue
@@ -381,59 +391,57 @@ def get_compilable_solc_versions(headers: Optional[Dict] = None) -> List[Version
return sorted(version_list, reverse=True)
-def get_installed_solc_versions(solcx_binary_path: Union[Path, str] = None) -> List[Version]:
+def get_installed_solc_versions(
+ solcx_binary_path: Optional[Union[Path, str]] = None
+) -> List[Version]:
"""
- Return a list of currently installed `solc` versions.
+ Return a list of currently installed ``solc`` versions.
- Arguments
- ---------
- solcx_binary_path : Path | str, optional
- User-defined path, used to override the default installation directory.
+ Args:
+ solcx_binary_path (Optional[Union[Path, str]]): User-defined path,
+ used to override the default installation directory.
- Returns
- -------
- List
- List of Version objects of installed `solc` versions.
+ Returns:
+ List: List of Version objects of installed ``solc`` versions.
"""
- install_path = get_solcx_install_folder(solcx_binary_path)
+ install_path = get_solcx_install_folder(solcx_binary_path=solcx_binary_path)
return sorted([Version(i.name[6:]) for i in install_path.glob("solc-v*")], reverse=True)
def install_solc(
version: Union[str, Version] = "latest",
show_progress: bool = False,
- solcx_binary_path: Union[Path, str] = None,
+ solcx_binary_path: Optional[Union[Path, str]] = None,
) -> Version:
"""
- Download and install a precompiled version of `solc`.
-
- Arguments
- ---------
- version : str | Version, optional
- Version of `solc` to install. Default is the newest available version.
- show_progress : bool, optional
- If True, display a progress bar while downloading. Requires installing
- the `tqdm` package.
- solcx_binary_path : Path | str, optional
- User-defined path, used to override the default installation directory.
-
- Returns
- -------
- Version
- installed solc version
+ Download and install a precompiled version of ``solc``.
+
+ Args:
+ version (Union[str, Version]): Version of ``solc`` to install.
+ Default is the newest available version.
+ show_progress (bool): If ``True``, display a progress bar while
+ downloading. Requires installing the ``tqdm`` package.
+ solcx_binary_path (Optional[Union[Path, str]]): User-defined path,
+ used to override the default installation directory.
+
+ Returns:
+ Version: installed solc version
"""
- if version == "latest":
- version = get_installable_solc_versions()[0]
- else:
- version = _convert_and_validate_version(version)
+ version = (
+ get_installable_solc_versions()[0]
+ if version == "latest"
+ else _convert_and_validate_version(version)
+ )
os_name = _get_os_name()
process_lock = get_process_lock(str(version))
with process_lock:
if _check_for_installed_version(version, solcx_binary_path):
- path = get_solcx_install_folder(solcx_binary_path).joinpath(f"solc-v{version}")
+ path = get_solcx_install_folder(solcx_binary_path=solcx_binary_path).joinpath(
+ f"solc-v{version}"
+ )
LOGGER.info(f"solc {version} already installed at: {path}")
return version
@@ -447,15 +455,17 @@ def install_solc(
except KeyError:
raise SolcInstallationError(f"Solc binary for v{version} is not available for this OS")
- if os_name == "linux":
- _install_solc_unix(version, filename, show_progress, solcx_binary_path)
- elif os_name == "macosx":
- _install_solc_unix(version, filename, show_progress, solcx_binary_path)
+ if os_name in ("linux", "macosx"):
+ _install_solc_unix(
+ version, filename, show_progress, solcx_binary_path=solcx_binary_path
+ )
elif os_name == "windows":
- _install_solc_windows(version, filename, show_progress, solcx_binary_path)
+ _install_solc_windows(
+ version, filename, show_progress, solcx_binary_path=solcx_binary_path
+ )
try:
- _validate_installation(version, solcx_binary_path)
+ _validate_installation(version, solcx_binary_path=solcx_binary_path)
except SolcInstallationError as exc:
if os_name != "windows":
exc.args = (
@@ -468,50 +478,61 @@ def install_solc(
def compile_solc(
- version: Version, show_progress: bool = False, solcx_binary_path: Union[Path, str] = None
+ version: Optional[Union[str, Version]] = None,
+ show_progress: bool = False,
+ solcx_binary_path: Optional[Union[Path, str]] = None,
) -> Version:
"""
Install a version of `solc` by downloading and compiling source code.
- Arguments
- ---------
- version : str | Version, optional
- Version of `solc` to install. Default is the newest available version.
- show_progress : bool, optional
- If True, display a progress bar while downloading. Requires installing
- the `tqdm` package.
- solcx_binary_path : Path | str, optional
- User-defined path, used to override the default installation directory.
-
- Returns
- -------
- Version
- installed solc version
+ Args:
+ version (Union[str, Version]): Version of `solc` to install.
+ Use literal ``"latest"`` or ``None`` to install the latest version.
+ Default is the latest.
+ show_progress (bool): If ``True``, display a progress bar while downloading.
+ Requires installing the `tqdm` package.
+ solcx_binary_path (Optional[Union[Path, str]]): User-defined path, used to
+ override the default installation directory.
+
+ Returns:
+ Version: The version of the compiler installed.
"""
if _get_os_name() == "windows":
raise OSError("Compiling from source is not supported on Windows systems")
- if version == "latest":
- version = get_compilable_solc_versions()[0]
+ if version in (None, "latest"):
+ solc_version = get_compilable_solc_versions()[0]
+
+ elif version is not None:
+ solc_version = _convert_and_validate_version(version)
+
else:
- version = _convert_and_validate_version(version)
+ # Shouldn't get here - but is for type-check.
+ raise ValueError(version)
- process_lock = get_process_lock(str(version))
+ process_lock = get_process_lock(str(solc_version))
with process_lock:
- if _check_for_installed_version(version, solcx_binary_path):
- path = get_solcx_install_folder(solcx_binary_path).joinpath(f"solc-v{version}")
- LOGGER.info(f"solc {version} already installed at: {path}")
- return version
+ if _check_for_installed_version(solc_version, solcx_binary_path):
+ path = get_solcx_install_folder(solcx_binary_path).joinpath(
+ f"solc-v{solc_version.base_version}"
+ )
+ LOGGER.info(f"solc {solc_version.base_version} already installed at: {path}")
+ return solc_version
temp_path = _get_temp_folder()
- download = SOURCE_DOWNLOAD_BASE.format(version, f"solidity_{version}.tar.gz")
- install_path = get_solcx_install_folder(solcx_binary_path).joinpath(f"solc-v{version}")
+ download = SOURCE_DOWNLOAD_BASE.format(
+ solc_version.base_version, f"solidity_{solc_version.base_version}.tar.gz"
+ )
+ install_path = get_solcx_install_folder(solcx_binary_path).joinpath(
+ f"solc-v{solc_version.base_version}"
+ )
content = _download_solc(download, show_progress)
with tarfile.open(fileobj=BytesIO(content)) as tar:
tar.extractall(temp_path)
- temp_path = temp_path.joinpath(f"solidity_{version}")
+
+ temp_path = temp_path.joinpath(f"solidity_{solc_version.base_version}")
try:
LOGGER.info("Running dependency installation script `install_deps.sh`...")
@@ -529,6 +550,7 @@ def compile_solc(
LOGGER.info(f"Running `{cmd[0]}`...")
subprocess.check_call(cmd, stderr=subprocess.DEVNULL)
temp_path.joinpath("build/solc/solc").rename(install_path)
+
except subprocess.CalledProcessError as exc:
err_msg = (
f"{cmd[0]} returned non-zero exit status {exc.returncode}"
@@ -546,13 +568,13 @@ def compile_solc(
os.chdir(original_path)
install_path.chmod(install_path.stat().st_mode | stat.S_IEXEC)
- _validate_installation(version, solcx_binary_path)
+ _validate_installation(solc_version, solcx_binary_path)
- return version
+ return solc_version
def _check_for_installed_version(
- version: Version, solcx_binary_path: Union[Path, str] = None
+ version: Union[str, Version], solcx_binary_path: Optional[Union[Path, str]] = None
) -> bool:
path = get_solcx_install_folder(solcx_binary_path).joinpath(f"solc-v{version}")
return path.exists()
@@ -578,7 +600,12 @@ def _download_solc(url: str, show_progress: bool) -> bytes:
raise DownloadError(
f"Received status code {response.status_code} when attempting to download from {url}"
)
- if not show_progress:
+
+ if show_progress and not tqdm:
+ LOGGER.warning("Must install `tqdm` to see download progress")
+ return response.content
+
+ elif not show_progress:
return response.content
total_size = int(response.headers.get("content-length", 0))
@@ -597,7 +624,9 @@ def _install_solc_unix(
version: Version, filename: str, show_progress: bool, solcx_binary_path: Union[Path, str, None]
) -> None:
download = BINARY_DOWNLOAD_BASE.format(_get_os_name(), filename)
- install_path = get_solcx_install_folder(solcx_binary_path).joinpath(f"solc-v{version}")
+ install_path = get_solcx_install_folder(solcx_binary_path=solcx_binary_path).joinpath(
+ f"solc-v{version}"
+ )
content = _download_solc(download, show_progress)
with open(install_path, "wb") as fp:
@@ -629,27 +658,32 @@ def _install_solc_windows(
def _validate_installation(version: Version, solcx_binary_path: Union[Path, str, None]) -> None:
binary_path = get_executable(version, solcx_binary_path)
try:
- installed_version = wrapper.get_solc_version(binary_path)
+ installed_version = wrapper.get_version_str_from_solc_binary(binary_path)
except Exception:
_unlink_solc(binary_path)
raise SolcInstallationError(
"Downloaded binary would not execute, or returned unexpected output."
)
- if installed_version.truncate() != version.truncate():
+ if Version(installed_version.replace("-nightly", "")).base_version != version.base_version:
+ # Without the nightly suffix, it should be the same!
_unlink_solc(binary_path)
raise UnexpectedVersionError(
f"Attempted to install solc v{version}, but got solc v{installed_version}"
)
- if installed_version != version:
+ if installed_version != version.base_version:
+ # If it does have the nightly suffix, then only warn.
warnings.warn(f"Installed solc version is v{installed_version}", UnexpectedVersionWarning)
- if not _default_solc_binary:
+
+ if not get_default_solc_binary():
set_solc_version(version)
+
LOGGER.info(f"solc {version} successfully installed at: {binary_path}")
try:
# try to set the result of `which`/`where` as the default
- _default_solc_binary = _get_which_solc()
+ if path := _get_which_solc():
+ _default_solc_binary = path
except Exception:
# if not available, use the most recent solcx installed version
if get_installed_solc_versions():
diff --git a/solcx/main.py b/solcx/main.py
index d00dd7f..d52e2aa 100644
--- a/solcx/main.py
+++ b/solcx/main.py
@@ -2,7 +2,7 @@
from pathlib import Path
from typing import Any, Dict, List, Optional, Union
-from semantic_version import Version
+from packaging.version import Version
from solcx import wrapper
from solcx.exceptions import ContractsNotFound, SolcError
@@ -11,41 +11,38 @@
def get_solc_version(with_commit_hash: bool = False) -> Version:
"""
- Get the version of the active `solc` binary.
+ Get the version of the active ``solc`` binary.
- Arguments
- ---------
- with_commit_hash : bool, optional
- If True, the commit hash is included within the version
+ Args:
+ with_commit_hash (bool): If ``True``, the commit hash is included
+ within the version. Defaults to ``False``.
- Returns
- -------
- Version
- solc version
+ Returns:
+ Version: solc version
"""
solc_binary = get_executable()
- return wrapper.get_solc_version(solc_binary, with_commit_hash)
+ return wrapper.get_solc_version(solc_binary, with_commit_hash=with_commit_hash)
def compile_source(
source: str,
- output_values: List = None,
- import_remappings: Union[Dict, List, str] = None,
- base_path: Union[Path, str] = None,
- allow_paths: Union[List, Path, str] = None,
- output_dir: Union[Path, str] = None,
+ output_values: Optional[List] = None,
+ import_remappings: Optional[Union[Dict, List, str]] = None,
+ base_path: Optional[Union[Path, str]] = None,
+ allow_paths: Optional[Union[List, Path, str]] = None,
+ output_dir: Optional[Union[Path, str]] = None,
overwrite: bool = False,
- evm_version: str = None,
- revert_strings: Union[List, str] = None,
- metadata_hash: str = None,
+ evm_version: Optional[str] = None,
+ revert_strings: Optional[Union[List, str]] = None,
+ metadata_hash: Optional[str] = None,
metadata_literal: bool = False,
optimize: bool = False,
- optimize_runs: int = None,
- optimize_yul: bool = False,
- no_optimize_yul: bool = False,
- yul_optimizations: int = None,
- solc_binary: Union[str, Path] = None,
- solc_version: Version = None,
+ optimize_runs: Optional[int] = None,
+ optimize_yul: Optional[bool] = None,
+ no_optimize_yul: Optional[bool] = None,
+ yul_optimizations: Optional[int] = None,
+ solc_binary: Optional[Union[str, Path]] = None,
+ solc_version: Optional[Union[str, Version]] = None,
allow_empty: bool = False,
**kwargs: Any,
) -> Dict:
@@ -55,60 +52,51 @@ def compile_source(
Compilation is handled via the `--combined-json` flag. Depending on the solc
version used, some keyword arguments may not be available.
- Arguments
- ---------
- source: str
- Solidity contract to be compiled.
- output_values : List, optional
- Compiler outputs to return. Valid options depend on the version of `solc`.
- If not given, all possible outputs for the active version are returned.
- import_remappings : Dict | List | str , optional
- Path remappings. May be given as a string or list of strings formatted as
- `"prefix=path"`, or a dict of `{"prefix": "path"}`.
- base_path : Path | str, optional
- Use the given path as the root of the source tree instead of the root
- of the filesystem.
- allow_paths : List | Path | str, optional
- A path, or list of paths, to allow for imports.
- output_dir : str, optional
- Creates one file per component and contract/file at the specified directory.
- overwrite : bool, optional
- Overwrite existing files (used in combination with `output_dir`)
- evm_version: str, optional
- Select the desired EVM version. Valid options depend on the `solc` version.
- revert_strings : List | str, optional
- Strip revert (and require) reason strings or add additional debugging
- information.
- metadata_hash : str, optional
- Choose hash method for the bytecode metadata or disable it.
- metadata_literal : bool, optional
- Store referenced sources as literal data in the metadata output.
- optimize : bool, optional
- Enable bytecode optimizer.
- optimize_runs : int, optional
- Set for how many contract runs to optimize. Lower values will optimize
- more for initial deployment cost, higher values will optimize more for
- high-frequency usage.
- optimize_yul: bool, optional
- Enable the yul optimizer.
- no_optimize_yul : bool, optional
- Disable the yul optimizer.
- yul_optimizations : int, optional
- Force yul optimizer to use the specified sequence of optimization steps
- instead of the built-in one.
- solc_binary : str | Path, optional
- Path of the `solc` binary to use. If not given, the currently active
- version is used (as set by `solcx.set_solc_version`)
- solc_version: Version, optional
- `solc` version to use. If not given, the currently active version is used.
- Ignored if `solc_binary` is also given.
- allow_empty : bool, optional
- If `True`, do not raise when no compiled contracts are returned.
-
- Returns
- -------
- Dict
- Compiler output. The source file name is given as ``.
+ Args:
+ source (str): Solidity contract to be compiled.
+ output_values (Optional[List]): Compiler outputs to return.
+ Valid options depend on the version of ``solc``. If not given,
+ all possible outputs for the active version are returned.
+ import_remappings (Optional[Union[Dict, List, str]]): Path remappings.
+ May be given as a string or list of strings formatted as
+ ``"prefix=path"``,or a dict of ``{"prefix": "path"}``.
+ base_path (Optional[Union[Path, str]]): Use the given path as the
+ root of the source tree instead of the root of the filesystem.
+ allow_paths (Optional[Union[List, Path, str]]): A path, or list of
+ paths, to allow for imports.
+ output_dir (Optional[str]): Creates one file per component and
+ contract/file at the specified directory.
+ overwrite (bool): Overwrite existing files, used in combination with
+ ``output_dir``.
+ evm_version (Optional[str]): Select the desired EVM version. Valid
+ options depend on the ``solc`` version.
+ revert_strings (Optional[List[str]]): Strip revert (and require)
+ reason strings or add additional debugging information.
+ metadata_hash (Optional[str]): Choose hash method for the bytecode
+ metadata or disable it.
+ metadata_literal (bool): Store referenced sources as literal data
+ in the metadata output.
+ optimize (bool): Enable bytecode optimizer. Defauls to ``False``.
+ optimize_runs (Optional[int]): Set for how many contract runs to
+ optimize. Lower values will optimize more for initial deployment
+ cost, higher values will optimize more for high-frequency usage.
+ optimize_yul (Optional[bool]): Enable the Yul optimizer. Defaults to
+ ``None``.
+ no_optimize_yul (Optional[bool]): Disable the Yul optimizer. Defaults to
+ ``None``.
+ yul_optimizations (Optional[int]): Force yul optimizer to use the
+ specified sequence of optimization steps instead of the built-in one.
+ solc_binary (Optional[Union[str, Path]]): Path of the `solc` binary to
+ use. If not given, the currently active version is used, as set by
+ :meth:`solcx.set_solc_version`.
+ solc_version (Optional[Union[str, Version]]): ``solc`` version to use. If not given,
+ the currently active version is used. Ignored if `solc_binary` is also
+ given.
+ allow_empty (bool): If ``True``, do not raise when no compiled contracts
+ are returned.
+
+ Returns:
+ Dict: Compiler output. The source file name is given as ````.
"""
return _compile_combined_json(
solc_binary=solc_binary,
@@ -126,6 +114,7 @@ def compile_source(
metadata_literal=metadata_literal,
optimize=optimize,
optimize_runs=optimize_runs,
+ optimize_yul=optimize_yul,
no_optimize_yul=no_optimize_yul,
yul_optimizations=yul_optimizations,
allow_empty=allow_empty,
@@ -135,86 +124,77 @@ def compile_source(
def compile_files(
source_files: Union[List, Path, str],
- output_values: List = None,
- import_remappings: Union[Dict, List, str] = None,
- base_path: Union[Path, str] = None,
- allow_paths: Union[List, Path, str] = None,
- output_dir: Union[Path, str] = None,
+ output_values: Optional[List] = None,
+ import_remappings: Optional[Union[Dict, List, str]] = None,
+ base_path: Optional[Union[Path, str]] = None,
+ allow_paths: Optional[Union[List, Path, str]] = None,
+ output_dir: Optional[Union[Path, str]] = None,
overwrite: bool = False,
- evm_version: str = None,
- revert_strings: Union[List, str] = None,
- metadata_hash: str = None,
+ evm_version: Optional[str] = None,
+ revert_strings: Optional[Union[List, str]] = None,
+ metadata_hash: Optional[str] = None,
metadata_literal: bool = False,
optimize: bool = False,
- optimize_runs: int = None,
- optimize_yul: bool = False,
- no_optimize_yul: bool = False,
- yul_optimizations: int = None,
- solc_binary: Union[str, Path] = None,
- solc_version: Version = None,
+ optimize_runs: Optional[int] = None,
+ optimize_yul: Optional[bool] = None,
+ no_optimize_yul: Optional[bool] = None,
+ yul_optimizations: Optional[int] = None,
+ solc_binary: Optional[Union[str, Path]] = None,
+ solc_version: Optional[Union[str, Version]] = None,
allow_empty: bool = False,
**kwargs: Any,
) -> Dict:
"""
Compile one or more Solidity source files.
- Compilation is handled via the `--combined-json` flag. Depending on the solc
- version used, some keyword arguments may not be available.
-
- Arguments
- ---------
- source_files: List | Path | str
- Path, or list of paths, of Solidity source files to be compiled.
- output_values : List, optional
- Compiler outputs to return. Valid options depend on the version of `solc`.
- If not given, all possible outputs for the active version are returned.
- import_remappings : Dict | List | str , optional
- Path remappings. May be given as a string or list of strings formatted as
- `"prefix=path"`, or a dict of `{"prefix": "path"}`.
- base_path : Path | str, optional
- Use the given path as the root of the source tree instead of the root
- of the filesystem.
- allow_paths : List | Path | str, optional
- A path, or list of paths, to allow for imports.
- output_dir : str, optional
- Creates one file per component and contract/file at the specified directory.
- overwrite : bool, optional
- Overwrite existing files (used in combination with `output_dir`)
- evm_version: str, optional
- Select the desired EVM version. Valid options depend on the `solc` version.
- revert_strings : List | str, optional
- Strip revert (and require) reason strings or add additional debugging
- information.
- metadata_hash : str, optional
- Choose hash method for the bytecode metadata or disable it.
- metadata_literal : bool, optional
- Store referenced sources as literal data in the metadata output.
- optimize : bool, optional
- Enable bytecode optimizer.
- optimize_runs : int, optional
- Set for how many contract runs to optimize. Lower values will optimize
- more for initial deployment cost, higher values will optimize more for
- high-frequency usage.
- optimize_yul: bool, optional
- Enable the yul optimizer.
- no_optimize_yul : bool, optional
- Disable the yul optimizer.
- yul_optimizations : int, optional
- Force yul optimizer to use the specified sequence of optimization steps
- instead of the built-in one.
- solc_binary : str | Path, optional
- Path of the `solc` binary to use. If not given, the currently active
- version is used (as set by `solcx.set_solc_version`)
- solc_version: Version, optional
- `solc` version to use. If not given, the currently active version is used.
- Ignored if `solc_binary` is also given.
- allow_empty : bool, optional
- If `True`, do not raise when no compiled contracts are returned.
-
- Returns
- -------
- Dict
- Compiler output
+ Compilation is handled via the ``--combined-json`` flag. Depending on the
+ solc version used, some keyword arguments may not be available.
+
+ Args:
+ source_files (Union[List, Path, str]): Path, or list of paths, of Solidity
+ source files to be compiled.
+ output_values (Optional[List]): Compiler outputs to return. Valid options
+ depend on the version of ``solc``. If not given, all possible outputs for
+ the active version are returned.
+ import_remappings (Optional[Union[Dict, List, str]]): Path remappings. May
+ be given as a string or list of strings formatted as ``"prefix=path"``,
+ or a dict of ``{"prefix": "path"}``.
+ base_path (Optional[Union[Path, str]]): Use the given path as the root of
+ the source tree instead of the root of the filesystem.
+ allow_paths (Optional[Union[List, Path, str]]): A path, or list of paths,
+ to allow for imports.
+ output_dir (Optional[Union[Path, str]]): Creates one file per component
+ and contract/file at the specified directory.
+ overwrite (bool): Overwrite existing files, used in combination with
+ ``output_dir``.
+ evm_version (Optional[str]): Select the desired EVM version. Valid
+ options depend on the ``solc`` version.
+ revert_strings (Optional[Union[List, str]]): Strip revert (and require)
+ reason strings or add additional debugging information.
+ metadata_hash (Optional[str]): Choose hash method for the bytecode
+ metadata or disable it.
+ metadata_literal (Optional[bool]): Store referenced sources as literal
+ data in the metadata output.
+ optimize (bool): Enable bytecode optimizer. Defaults to ``False``.
+ optimize_runs (Optional[int]): Set for how many contract runs to optimize.
+ Lower values will optimize more for initial deployment cost, higher
+ values will optimize more for high-frequency usage.
+ optimize_yul (Optional[bool]): Enable the Yul optimizer. Defaults to
+ ``None``.
+ no_optimize_yul (Optional[bool]): Disable the Yul optimizer. Defaults to
+ ``None``.
+ yul_optimizations (Optional[int]): Force yul optimizer to use the
+ specified sequence of optimization steps instead of the built-in one.
+ solc_binary (Optional[Union[str, Path]]): Path of the `solc` binary to
+ use. If not given, the currently active version is used, as set by
+ :meth:`solcx.set_solc_version`.
+ solc_version (Optional[Union[str, Version]]): ``solc`` version to use. If not given,
+ the currently active version is used. Ignored if `solc_binary` is also given.
+ allow_empty (bool): If ``True``, do not raise when no compiled contracts are
+ returned. defaults to ``False``.
+
+ Returns:
+ Dict: Compiler output
"""
return _compile_combined_json(
solc_binary=solc_binary,
@@ -232,6 +212,7 @@ def compile_files(
metadata_literal=metadata_literal,
optimize=optimize,
optimize_runs=optimize_runs,
+ optimize_yul=optimize_yul,
no_optimize_yul=no_optimize_yul,
yul_optimizations=yul_optimizations,
allow_empty=allow_empty,
@@ -239,7 +220,7 @@ def compile_files(
)
-def _get_combined_json_outputs(solc_binary: Union[Path, str] = None) -> str:
+def _get_combined_json_outputs(solc_binary: Optional[Union[Path, str]] = None) -> str:
if solc_binary is None:
solc_binary = get_executable()
@@ -267,15 +248,13 @@ def _parse_compiler_output(stdoutdata: str) -> Dict:
def _compile_combined_json(
output_values: Optional[List] = None,
solc_binary: Union[str, Path, None] = None,
- solc_version: Optional[Version] = None,
+ solc_version: Optional[Union[Version, str]] = None,
output_dir: Union[str, Path, None] = None,
overwrite: Optional[bool] = False,
allow_empty: Optional[bool] = False,
**kwargs: Any,
) -> Dict:
-
- if solc_binary is None:
- solc_binary = get_executable(solc_version)
+ solc_binary = get_executable(version=solc_version) if solc_binary is None else solc_binary
if output_values is None:
combined_json = _get_combined_json_outputs(solc_binary)
@@ -324,12 +303,12 @@ def _compile_combined_json(
def compile_standard(
input_data: Dict,
- base_path: str = None,
- allow_paths: List = None,
- output_dir: str = None,
+ base_path: Optional[Union[str, Path]] = None,
+ allow_paths: Optional[Union[List, Path, str]] = None,
+ output_dir: Optional[str] = None,
overwrite: bool = False,
- solc_binary: Union[str, Path] = None,
- solc_version: Version = None,
+ solc_binary: Optional[Union[str, Path]] = None,
+ solc_version: Optional[Union[str, Version]] = None,
allow_empty: bool = False,
) -> Dict:
"""
@@ -338,32 +317,26 @@ def compile_standard(
See the Solidity documentation for details on the expected JSON input and output
formats.
- Arguments
- ---------
- input_data : Dict
- Compiler JSON input.
- base_path : Path | str, optional
- Use the given path as the root of the source tree instead of the root
- of the filesystem.
- allow_paths : List | Path | str, optional
- A path, or list of paths, to allow for imports.
- output_dir : str, optional
- Creates one file per component and contract/file at the specified directory.
- overwrite : bool, optional
- Overwrite existing files (used in combination with `output_dir`)
- solc_binary : str | Path, optional
- Path of the `solc` binary to use. If not given, the currently active
- version is used (as set by `solcx.set_solc_version`)
- solc_version: Version, optional
- `solc` version to use. If not given, the currently active version is used.
- Ignored if `solc_binary` is also given.
- allow_empty : bool, optional
- If `True`, do not raise when no compiled contracts are returned.
-
- Returns
- -------
- Dict
- Compiler JSON output.
+ Args:
+ input_data (Dict): Compiler JSON input.
+ base_path (Optional[Union[str, Path]]): Use the given path as the root of the
+ source tree instead of the root of the filesystem.
+ allow_paths (Optional[Union[List, Path, str]]): A path, or list of paths, to
+ allow for imports.
+ output_dir (Optional[str]): Creates one file per component and contract/file
+ at the specified directory.
+ overwrite (bool): Overwrite existing files, used in combination with
+ ``output_dir``.
+ solc_binary (Optional[Union[str, Path]]): Path of the `solc` binary to use.
+ If not given, the currently active version is used, as set by
+ :meth:`solcx.set_solc_version`.
+ solc_version (Optional[Union[str, Version]]): ``solc`` version to use. If not given,
+ the currently active version is used. Ignored if ``solc_binary`` is also given.
+ allow_empty (bool): If ``True``, do not raise when no compiled contracts are returned.
+ Defaults to ``False``.
+
+ Returns:
+ Dict: Compiler JSON output.
"""
if not input_data.get("sources") and not allow_empty:
raise ContractsNotFound(
@@ -371,9 +344,7 @@ def compile_standard(
stdin_data=json.dumps(input_data, sort_keys=True, indent=2),
)
- if solc_binary is None:
- solc_binary = get_executable(solc_version)
-
+ solc_binary = get_executable(version=solc_version) if solc_binary is None else solc_binary
stdoutdata, stderrdata, command, proc = wrapper.solc_wrapper(
solc_binary=solc_binary,
stdin=json.dumps(input_data),
@@ -410,33 +381,28 @@ def compile_standard(
def link_code(
unlinked_bytecode: str,
libraries: Dict,
- solc_binary: Union[str, Path] = None,
- solc_version: Version = None,
+ solc_binary: Optional[Union[str, Path]] = None,
+ solc_version: Optional[Version] = None,
) -> str:
"""
Add library addresses into unlinked bytecode.
- Arguments
- ---------
- unlinked_bytecode : str
- Compiled bytecode containing one or more library placeholders.
- libraries : Dict
- Library addresses given as {"library name": "address"}
- solc_binary : str | Path, optional
- Path of the `solc` binary to use. If not given, the currently active
- version is used (as set by `solcx.set_solc_version`)
- solc_version: Version, optional
- `solc` version to use. If not given, the currently active version is used.
- Ignored if `solc_binary` is also given.
-
- Returns
- -------
- str
- Linked bytecode
+ Args:
+ unlinked_bytecode (str): Compiled bytecode containing one or
+ more library placeholders.
+ libraries (Dict): Library addresses given as
+ ``{"library name": "address"}``.
+ solc_binary (Optional[Union[str, Path]]): Path of the ``solc``
+ binary to use. If not given, the currently active
+ version is used, as set by :meth:`solcx.set_solc_version`.
+ solc_version (Optional[Version]): `solc` version to use. If
+ not given, the currently active version is used. Ignored if
+ ``solc_binary`` is also given.
+
+ Returns:
+ str: Linked bytecode
"""
- if solc_binary is None:
- solc_binary = get_executable(solc_version)
-
+ solc_binary = get_executable(version=solc_version) if solc_binary is None else solc_binary
library_list = [f"{name}:{address}" for name, address in libraries.items()]
stdoutdata = wrapper.solc_wrapper(
diff --git a/solcx/wrapper.py b/solcx/wrapper.py
index fa820fc..3ba92c1 100644
--- a/solcx/wrapper.py
+++ b/solcx/wrapper.py
@@ -1,9 +1,9 @@
import re
import subprocess
from pathlib import Path
-from typing import Any, Dict, List, Tuple, Union
+from typing import Any, Dict, List, Optional, Tuple, Union
-from semantic_version import Version
+from packaging.version import Version
from solcx import install
from solcx.exceptions import SolcError, UnknownOption, UnknownValue
@@ -17,19 +17,19 @@ def _get_solc_version(solc_binary: Union[Path, str], with_commit_hash: bool = Fa
return get_solc_version(solc_binary, with_commit_hash=with_commit_hash)
-def get_solc_version(solc_binary: Union[Path, str], with_commit_hash: bool = False) -> Version:
+def get_version_str_from_solc_binary(solc_binary: Union[Path, str]) -> str:
stdout_data = subprocess.check_output([str(solc_binary), "--version"], encoding="utf8")
- try:
- match = next(re.finditer(VERSION_REGEX, stdout_data))
- version_str = "".join(match.groups())
- except StopIteration:
+ if not (match := next(re.finditer(VERSION_REGEX, stdout_data), None)):
raise SolcError("Could not determine the solc binary version")
- version = Version.coerce(version_str)
- if with_commit_hash:
- return version
- else:
- return version.truncate()
+ # NOTE: May include "-nightly" suffix.
+ return "".join(match.groups())
+
+
+def get_solc_version(solc_binary: Union[Path, str], with_commit_hash: bool = False) -> Version:
+ version_str = get_version_str_from_solc_binary(solc_binary)
+ version = Version(version_str.replace("-nightly", ""))
+ return version if with_commit_hash else Version(version.base_version)
def _to_string(key: str, value: Any) -> str:
@@ -45,68 +45,58 @@ def _to_string(key: str, value: Any) -> str:
def solc_wrapper(
- solc_binary: Union[Path, str] = None,
- stdin: str = None,
- source_files: Union[List, Path, str] = None,
- import_remappings: Union[Dict, List, str] = None,
- success_return_code: int = None,
+ solc_binary: Optional[Union[Path, str]] = None,
+ stdin: Optional[str] = None,
+ source_files: Optional[Union[List, Path, str]] = None,
+ import_remappings: Optional[Union[Dict, List, str]] = None,
+ success_return_code: Optional[int] = None,
**kwargs: Any,
) -> Tuple[str, str, List, subprocess.Popen]:
"""
- Wrapper function for calling to `solc`.
-
- Arguments
- ---------
- solc_binary : Path | str, optional
- Location of the `solc` binary. If not given, the current default binary is used.
- stdin : str, optional
- Input to pass to `solc` via stdin
- source_files : list | Path | str, optional
- Path, or list of paths, of sources to compile
- import_remappings : Dict | List | str, optional
- Path remappings. May be given as a string or list of strings formatted as `"prefix=path"`
- or a dict of `{"prefix": "path"}`
- success_return_code : int, optional
- Expected exit code. Raises `SolcError` if the process returns a different value.
-
- Keyword Arguments
- -----------------
- **kwargs : Any
- Flags to be passed to `solc`. Keywords are converted to flags by prepending `--` and
- replacing `_` with `-`, for example the keyword `evm_version` becomes `--evm-version`.
- Values may be given in the following formats:
-
- * `False`, `None`: ignored
- * `True`: flag is used without any arguments
+ Wrapper function for calling to ``solc``.
+
+ Args:
+ solc_binary (Optional[Union[Path, str]]): Location of the
+ ``solc`` binary. If not given, the current default binary is used.
+ stdin (Optional[str]): Input to pass to ``solc`` via stdin.
+ source_files (Optional[Union[List, Path, str]]): Path, or list of
+ paths, of sources to compile
+ import_remappings (Optional[Union[Dict, List, str]]): Path remappings.
+ May be given as a string or list of strings, formatted as ``"prefix=path"``
+ or a dict of ``{"prefix": "path"}``.
+ success_return_code (Optional[int]): Expected exit code.
+ Raises :class:`~solcx.exceptions.SolcError`` if the process returns a
+ different value.
+ **kwargs (Any): Flags to be passed to ``solc``. Keywords are converted to
+ flags by prepending ``--`` and replacing ``_`` with ``-``, for example the
+ keyword ``evm_version`` becomes ``--evm-version``. Values may be given in
+ the following formats:
+
+ * ``False``, ``None``: ignored
+ * ``True``: flag is used without any arguments
* str: given as an argument without modification
* int: given as an argument, converted to a string
- * Path: converted to a string via `Path.as_posix()`
- * List, Tuple: elements are converted to strings and joined with `,`
-
- Returns
- -------
- str
- Process `stdout` output
- str
- Process `stderr` output
- List
- Full command executed by the function
- Popen
- Subprocess object used to call `solc`
+ * Path: converted to a string via ``Path.as_posix()``
+ * List, Tuple: elements are converted to strings and joined with ``,``
+
+ Returns:
+ str: Process ``stdout`` output.
+ str: Process ``stderr`` output.
+ List: Full command executed by the function.
+ Popen: Subprocess object used to call ``solc``.
"""
- if solc_binary:
- solc_binary = Path(solc_binary)
- else:
- solc_binary = install.get_executable()
-
+ solc_binary = Path(solc_binary) if solc_binary else install.get_executable()
solc_version = get_solc_version(solc_binary)
command: List = [str(solc_binary)]
- if success_return_code is None:
- if "help" in kwargs and solc_version < Version("0.8.10"):
- success_return_code = 1
- else:
- success_return_code = 0
+ if (
+ success_return_code is None
+ and ("--help" in command or "help" in kwargs)
+ and Version(solc_version.base_version) < Version("0.8.10")
+ ):
+ success_return_code = 1
+ else:
+ success_return_code = success_return_code or 0
if source_files is not None:
if isinstance(source_files, (str, Path)):
@@ -149,17 +139,24 @@ def solc_wrapper(
stdoutdata, stderrdata = proc.communicate(stdin)
+ stderrdata = (
+ stderrdata.replace("Error: ", "") if stderrdata.startswith("Error: ") else stderrdata
+ )
+
if proc.returncode != success_return_code:
if stderrdata.startswith("unrecognised option"):
# unrecognised option ''
flag = stderrdata.split("'")[1]
- raise UnknownOption(f"solc {solc_version} does not support the '{flag}' option'")
+ raise UnknownOption(
+ f"solc {solc_version.base_version} does not support the '{flag}' option'"
+ )
if stderrdata.startswith("Invalid option"):
# Invalid option to :