Skip to content

Commit

Permalink
feat: pyproject toml project support
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey committed Oct 17, 2024
1 parent c2f190a commit 024fb97
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 74 deletions.
14 changes: 13 additions & 1 deletion src/ape/api/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,25 @@ def is_valid(self) -> bool:

@cached_property
def config_file(self) -> Path:
if self._using_pyproject_toml:
return self._pyproject_toml

# else: check for an ape-config file.
for ext in self.EXTENSIONS:
path = self.path / f"{self.CONFIG_FILE_NAME}{ext}"
if path.is_file():
return path

# Default
# Default: non-existing ape-config.yaml file.
return self.path / f"{self.CONFIG_FILE_NAME}.yaml"

@property
def _pyproject_toml(self) -> Path:
return self.path / "pyproject.toml"

@property
def _using_pyproject_toml(self) -> bool:
return self._pyproject_toml.is_file() and "[tool.ape" in self._pyproject_toml.read_text()

def extract_config(self, **overrides) -> ApeConfig:
return ApeConfig.validate_file(self.config_file, **overrides)
2 changes: 2 additions & 0 deletions src/ape/managers/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -1763,6 +1763,8 @@ def unpack(self, destination: Path, config_override: Optional[dict] = None) -> "
path.write_text(str(src.content), encoding="utf8")

# Unpack config file.
# NOTE: Always unpacks into a regular .yaml config file for simplicity
# and maximum portibility.
self.config.write_to_disk(destination / "ape-config.yaml")

return LocalProject(destination, config_override=config_override)
Expand Down
147 changes: 99 additions & 48 deletions tests/functional/test_config.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import re
from pathlib import Path
from typing import Optional, Union

Expand All @@ -15,6 +16,90 @@
from ape_networks import CustomNetwork
from tests.functional.conftest import PROJECT_WITH_LONG_CONTRACTS_FOLDER

CONTRACTS_FOLDER = "pathsomewhwere"
NUMBER_OF_TEST_ACCOUNTS = 31
YAML_CONTENT = rf"""
contracts_folder: "{CONTRACTS_FOLDER}"
dependencies:
- name: "openzeppelin"
github: "OpenZeppelin/openzeppelin-contracts"
version: "4.5.0"
plugins:
- name: "hardhat"
- name: "solidity"
version: "0.8.1"
test:
number_of_accounts: "{NUMBER_OF_TEST_ACCOUNTS}"
compile:
exclude:
- "exclude_dir"
- "Excl*.json"
- r"Ignore\w*\.json"
""".lstrip()
JSON_CONTENT = f"""
{{
"contracts_folder": "{CONTRACTS_FOLDER}",
"dependencies": [
{{
"name": "openzeppelin",
"github": "OpenZeppelin/openzeppelin-contracts",
"version": "4.5.0"
}}
],
"plugins": [
{{
"name": "hardhat"
}},
{{
"name": "solidity",
"version": "0.8.1"
}}
],
"test": {{
"number_of_accounts": "{NUMBER_OF_TEST_ACCOUNTS}"
}},
"compile": {{
"exclude": [
"exclude_dir",
"Excl*.json",
"r\\"Ignore\\\\w*\\\\.json\\""
]
}}
}}
""".lstrip()
PYPROJECT_TOML = rf"""
[tool.ape]
contracts_folder = "{CONTRACTS_FOLDER}"
[[tool.ape.dependencies]]
name = "openzeppelin"
github = "OpenZeppelin/openzeppelin-contracts"
version = "4.5.0"
[[tool.ape.plugins]]
name = "hardhat"
[[tool.ape.plugins]]
name = "solidity"
version = "0.8.1"
[tool.ape.test]
number_of_accounts = {NUMBER_OF_TEST_ACCOUNTS}
[tool.ape.compile]
exclude = ["exclude_dir", "Excl*.json", 'r"Ignore\w*\.json"']
""".lstrip()
EXT_TO_CONTENT = {
".yml": YAML_CONTENT,
".yaml": YAML_CONTENT,
".json": JSON_CONTENT,
".toml": PYPROJECT_TOML,
}


def test_model_validate_empty():
data: dict = {}
Expand All @@ -41,61 +126,27 @@ def test_model_validate_path_contracts_folder():
assert cfg.contracts_folder == str(path)


@pytest.mark.parametrize("ext", ("yml", "yaml"))
def test_validate_file_config(ext):
contracts_folder = "pathtowherever"
with create_tempdir() as temp_dir:
file = temp_dir / f"ape-config.{ext}"
file.write_text(f"contracts_folder: {contracts_folder}")
actual = ApeConfig.validate_file(file)

assert actual.contracts_folder == contracts_folder


def test_validate_json_file():
value = "pathtowherever"
with create_tempdir() as temp_dir:
file = temp_dir / "ape-config.json"
file.write_text(f'{{"contracts_folder": "{value}"}}')
actual = ApeConfig.validate_file(file)

assert actual.contracts_folder == value


def test_validate_pyproject_toml():
contracts_folder = "pathtowherever"
number_of_test_accounts = 31
content = f"""
[tool.ape]
contracts_folder = "{contracts_folder}"
[[tool.ape.dependencies]]
name = "openzeppelin"
github = "OpenZeppelin/openzeppelin-contracts"
version = "4.5.0"
[[tool.ape.plugins]]
name = "hardhat"
[[tool.ape.plugins]]
name = "solidity"
version = "0.8.1"
[tool.ape.test]
number_of_accounts = {number_of_test_accounts}
""".lstrip()
@pytest.mark.parametrize(
"file", ("ape-config.yml", "ape-config.yaml", "ape-config.json", "pyproject.toml")
)
def test_validate_file(file):
content = EXT_TO_CONTENT[Path(file).suffix]
with create_tempdir() as temp_dir:
file = temp_dir / "pyproject.toml"
file.write_text(content)
actual = ApeConfig.validate_file(file)
path = temp_dir / file
path.write_text(content)
actual = ApeConfig.validate_file(path)

assert actual.contracts_folder == contracts_folder
assert actual.test.number_of_accounts == number_of_test_accounts
assert actual.contracts_folder == CONTRACTS_FOLDER
assert actual.test.number_of_accounts == NUMBER_OF_TEST_ACCOUNTS
assert len(actual.dependencies) == 1
assert actual.dependencies[0]["name"] == "openzeppelin"
assert actual.dependencies[0]["github"] == "OpenZeppelin/openzeppelin-contracts"
assert actual.dependencies[0]["version"] == "4.5.0"
assert actual.plugins == [{"name": "hardhat"}, {"name": "solidity", "version": "0.8.1"}]
assert re.compile("Ignore\\w*\\.json") in actual.compile.exclude
assert "exclude_dir" in actual.compile.exclude
assert ".cache" in actual.compile.exclude
assert "Excl*.json" in actual.compile.exclude


def test_validate_file_expands_env_vars():
Expand Down
25 changes: 0 additions & 25 deletions tests/integration/cli/projects/with-contracts/ape-config.yaml

This file was deleted.

23 changes: 23 additions & 0 deletions tests/integration/cli/projects/with-contracts/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[tool.ape]
name = "withcontracts"

[[tool.ape.dependencies]]
name = "foodep"
local = "./dep"

[[tool.ape.dependencies]]
name = "depcontractsfolderroot"
local = "./dep_contracts_folder_root"

[tool.ape.dependencies.config_override]
contracts_folder = "."

[[tool.ape.dependencies]]
name = "depwithunregisteredcontracts"
local = "./dep_with_sol_and_vy"

[tool.ape.test]
disconnect_providers_after = false

[tool.ape.compile]
exclude = ["exclude_dir", "Excl*.json", 'r"Ignore\w*\.json"']

0 comments on commit 024fb97

Please sign in to comment.