Skip to content

Commit

Permalink
feat: better CLI message when compiling a dependency produces no cont…
Browse files Browse the repository at this point in the history
…racts (ApeWorX#2130)
  • Loading branch information
antazoey authored Jun 12, 2024
1 parent 882526e commit 8ad275d
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 18 deletions.
29 changes: 27 additions & 2 deletions src/ape/managers/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -749,7 +749,32 @@ def compile(
self.project.reconfigure(**override)
self._cache.cache_api(self.api)

return self.project.load_contracts(use_cache=use_cache)
result = self.project.load_contracts(use_cache=use_cache)
if not result:
contracts_folder = self.project.contracts_folder
message = "Compiling dependency produced no contract types."
if isinstance(self.project, LocalProject):
all_files = [x.name for x in get_all_files_in_directory(contracts_folder)]
has_solidity_sources = any(get_full_extension(Path(x)) == ".sol" for x in all_files)
has_vyper_sources = any(
get_full_extension(Path(x)) in (".vy", ".vyi") for x in all_files
)
compilers = self.compiler_manager.registered_compilers
warn_sol = has_solidity_sources and ".sol" not in compilers
warn_vyper = has_vyper_sources and ".vy" not in compilers
suffix = ""
if warn_sol:
suffix = "Try installing 'ape-solidity'"
if warn_vyper and warn_sol:
suffix += " or 'ape-vyper'"
elif warn_vyper:
suffix = "Try installing 'ape-vyper'"
if suffix:
message = f"{message} {suffix}."

logger.warning(message)

return result

def unpack(self, path: Path) -> Iterator["Dependency"]:
"""
Expand Down Expand Up @@ -2331,7 +2356,7 @@ def load_contracts(
starting = {
n: ContractContainer(ct)
for n, ct in (self.manifest.contract_types or {}).items()
if ct.source_id and (self.path / ct.source_id).is_file()
if use_cache and ct.source_id and (self.path / ct.source_id).is_file()
}
paths = self.sources.paths

Expand Down
28 changes: 13 additions & 15 deletions src/ape_pm/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,15 +293,7 @@ def compile(cli_ctx, name, version, force, config_override):
cfg["config_override"] = config_override

dependency = pm.dependencies.install(**cfg)
try:
dependency.compile(use_cache=not force)
except Exception as err:
cli_ctx.logger.error(str(err))
continue
else:
cli_ctx.logger.success(
f"Package '{dependency.name}@{dependency.version}' compiled."
)
_compile_dependency(cli_ctx, dependency, force)

if did_error:
sys.exit(1)
Expand All @@ -321,10 +313,16 @@ def compile(cli_ctx, name, version, force, config_override):
if config_override:
dependency.api.config_override = config_override

try:
dependency.compile(use_cache=not force)
except Exception as err:
cli_ctx.logger.error(str(err))
continue
else:
_compile_dependency(cli_ctx, dependency, force)


def _compile_dependency(cli_ctx, dependency: Dependency, force: bool):
try:
result = dependency.compile(use_cache=not force)
except Exception as err:
cli_ctx.logger.error(str(err))
else:
if result:
cli_ctx.logger.success(f"Package '{dependency.name}@{dependency.version}' compiled.")
# else: user should have received warning from `dependency.compile()` if there
# was no result.
30 changes: 30 additions & 0 deletions tests/functional/test_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from ape.managers.project import Dependency, LocalProject, PackagesCache, Project, ProjectManager
from ape.utils import create_tempdir
from ape_pm.dependency import GithubDependency, LocalDependency, NpmDependency
from tests.conftest import skip_if_plugin_installed


@pytest.fixture
Expand Down Expand Up @@ -543,6 +544,35 @@ def test_manifest_path(self, dependency, data_folder):
expected = data_folder / "packages" / "manifests" / name / "1_0_0.json"
assert actual == expected

def test_compile(self, project):
with create_tempdir() as path:
api = LocalDependency(local=path, name="ooga", version="1.0.0")
dependency = Dependency(api, project)
contract_path = dependency.project.contracts_folder / "CCC.json"
contract_path.write_text(
'[{"name":"foo","type":"fallback", "stateMutability":"nonpayable"}]'
)
result = dependency.compile()
assert len(result) == 1
assert result["CCC"].name == "CCC"

@skip_if_plugin_installed("vyper", "solidity")
def test_compile_missing_compilers(self, project, ape_caplog):
with create_tempdir() as path:
api = LocalDependency(local=path, name="ooga2", version="1.1.0")
dependency = Dependency(api, project)
sol_path = dependency.project.contracts_folder / "Sol.sol"
sol_path.write_text("// Sol")
vy_path = dependency.project.contracts_folder / "Vy.vy"
vy_path.write_text("# Vy")
expected = (
"Compiling dependency produced no contract types. "
"Try installing 'ape-solidity' or 'ape-vyper'."
)
result = dependency.compile()
assert len(result) == 0
assert expected in ape_caplog.head


class TestProject:
"""
Expand Down
3 changes: 3 additions & 0 deletions tests/integration/cli/projects/with-contracts/ape-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ dependencies:
config_override:
contracts_folder: .

- name: depwithunregisteredcontracts
local: ./dep_with_sol_and_vy

test:
# `false` because running pytest within pytest.
disconnect_providers_after: false
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// Solidity file test
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Vyper file test
24 changes: 23 additions & 1 deletion tests/integration/cli/test_pm.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import pytest

from tests.conftest import ApeSubprocessRunner
from tests.conftest import ApeSubprocessRunner, skip_if_plugin_installed
from tests.integration.cli.utils import github_xfail, run_once, skip_projects_except

EXPECTED_FAIL_MESSAGE = "Unknown package '{}'."
Expand Down Expand Up @@ -157,6 +157,28 @@ def test_compile_dependency(pm_runner, integ_project):
assert result.exit_code == 0, result.output
assert f"Package '{name}@local' compiled." in result.output

# Show it can happen more than once. (no --force this time).
result = pm_runner.invoke("compile", name)
assert result.exit_code == 0, result.output
assert f"Package '{name}@local' compiled." in result.output


@skip_if_plugin_installed("vyper", "solidity")
@skip_projects_except("with-contracts")
def test_compile_missing_compiler_plugins(pm_runner, integ_project, compilers):
pm_runner.project = integ_project
name = "depwithunregisteredcontracts"
result = pm_runner.invoke("compile", name, "--force")
expected = (
"Compiling dependency produced no contract types. "
"Try installing 'ape-solidity' or 'ape-vyper'"
)
assert expected in result.output

# Also show it happens when installing _all_.
result = pm_runner.invoke("compile", ".", "--force")
assert expected in result.output


@skip_projects_except("only-dependencies")
def test_uninstall(pm_runner, integ_project):
Expand Down

0 comments on commit 8ad275d

Please sign in to comment.