Skip to content

Commit

Permalink
fix: warn multiple license steada fail (#137)
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey authored Apr 12, 2024
1 parent 4104a3f commit 8e89555
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 14 deletions.
29 changes: 18 additions & 11 deletions ape_solidity/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -1011,9 +1011,8 @@ def get_first_version_pragma(source: str) -> str:
return ""


def get_licenses(source: str) -> List[Tuple[str, str]]:
matches = LICENSES_PATTERN.findall(source)
return matches
def get_licenses(src: str) -> List[Tuple[str, str]]:
return LICENSES_PATTERN.findall(src)


def process_licenses(contract: str) -> str:
Expand All @@ -1030,22 +1029,30 @@ def process_licenses(contract: str) -> str:
if not extracted_licenses:
return contract

# Get the unique license identifiers. We expect that all licenses in a contract are the same.
# The "root" license is most-likely last because import statements are
# replaced with their sources typically at the top of the file
license_line, root_license = extracted_licenses[-1]

# Get the unique license identifiers. All licenses in a contract _should_ be the same.
unique_license_identifiers = {
license_identifier for _, license_identifier in extracted_licenses
}

# If we have more than one unique license identifier, raise an error.
# If we have more than one unique license identifier, warn the user and use the root.
if len(unique_license_identifiers) > 1:
raise CompilerError(f"Conflicting licenses found: {unique_license_identifiers}")

# Get the first license line and identifier.
license_line, _ = extracted_licenses[0]
licenses_str = ", ".join(sorted(unique_license_identifiers))
logger.warning(
f"Conflicting licenses found: '{licenses_str}'. "
f"Using the root file's license '{root_license}'."
)

# Remove all of the license lines from the contract.
contract_without_licenses = contract.replace(license_line, "")
contract_without_licenses = contract
for license_tuple in extracted_licenses:
line = license_tuple[0]
contract_without_licenses = contract_without_licenses.replace(line, "")

# Prepend the contract with only one license line.
# Prepend the contract with only the root license line.
contract_with_single_license = f"{license_line}\n{contract_without_licenses}"

return contract_with_single_license
Expand Down
15 changes: 12 additions & 3 deletions tests/test_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from ape import reverts
from ape.contracts import ContractContainer
from ape.exceptions import CompilerError
from ape.logging import LogLevel
from packaging.version import Version
from pkg_resources import get_distribution
from requests.exceptions import ConnectionError
Expand Down Expand Up @@ -600,15 +601,23 @@ def test_via_ir(project, compiler):
compiler.config.via_ir = False


def test_flatten(project, compiler, data_folder):
def test_flatten(project, compiler, data_folder, caplog):
source_path = project.contracts_folder / "Imports.sol"
with pytest.raises(CompilerError):
with caplog.at_level(LogLevel.WARNING):
compiler.flatten_contract(source_path)
actual = caplog.messages[-1]
expected = (
"Conflicting licenses found: 'LGPL-3.0-only, MIT'. "
"Using the root file's license 'MIT'."
)
assert actual == expected

source_path = project.contracts_folder / "ImportingLessConstrainedVersion.sol"
flattened_source = compiler.flatten_contract(source_path)
flattened_source_path = data_folder / "ImportingLessConstrainedVersionFlat.sol"
assert str(flattened_source) == str(flattened_source_path.read_text())
actual = str(flattened_source)
expected = str(flattened_source_path.read_text())
assert actual == expected


def test_compile_code(compiler):
Expand Down

0 comments on commit 8e89555

Please sign in to comment.