Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,23 @@
ADDRESS_LENGTH = 20


def _describe(input_descriptor: InputERC7730Descriptor, source: HttpUrl | None) -> str:
"""Name a descriptor in a diagnostic.

``source`` is optional and is None for a local file, which is the usual case for the CLI,
so fall back to what the descriptor calls itself -- the same identifier the converted
output carries as its contract name.

:param input_descriptor: descriptor being converted
:param source: source URL, if one was supplied
:return: the most specific identifier available
"""
name = input_descriptor.metadata.contractName or getattr(input_descriptor.context, "id", None)
if name is not None and source is not None:
return f"{name} ({source})"
return str(name or source or "<unidentified>")


def erc7730_v2_descriptor_to_calldata_descriptors(
input_descriptor: InputERC7730Descriptor,
source: HttpUrl | None = None,
Expand Down Expand Up @@ -190,7 +207,7 @@ def erc7730_v2_descriptor_to_calldata_descriptors(
return output_descriptors

except Exception as e:
out.warning(f"Error processing v2 ERC-7730 file {source}, skipping it")
out.warning(f"Error processing v2 ERC-7730 descriptor {_describe(input_descriptor, source)}, skipping it")
exception_to_output(e, out)

return []
Expand Down
51 changes: 51 additions & 0 deletions tests/v2/convert/calldata/test_describe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from typing import Any

import pytest
from pydantic_string_url import HttpUrl

from erc7730.convert.calldata.convert_erc7730_v2_input_to_calldata import _describe
from erc7730.model.input.v2.descriptor import InputERC7730Descriptor

SOURCE = HttpUrl("https://example.com/calldata-MyContract.json")


def descriptor(*, context_id: str | None = None, contract_name: str | None = None) -> InputERC7730Descriptor:
context: dict[str, Any] = {
"contract": {"deployments": [{"chainId": 1, "address": "0x0000000000000000000000000000000000000001"}]}
}
if context_id is not None:
context["$id"] = context_id
metadata: dict[str, Any] = {"owner": "Someone"}
if contract_name is not None:
metadata["contractName"] = contract_name
return InputERC7730Descriptor.model_validate(
{"context": context, "metadata": metadata, "display": {"formats": {}}}, strict=True
)


def test_the_contract_name_is_preferred() -> None:
assert _describe(descriptor(context_id="Fallback", contract_name="MyContract"), None) == "MyContract"


def test_the_context_id_is_the_fallback() -> None:
"""A descriptor need not set contractName, and $id is what the output falls back to as well."""
assert _describe(descriptor(context_id="MyContract"), None) == "MyContract"


def test_a_source_is_kept_beside_the_name() -> None:
"""Both identify it, and a batch run over many files wants the path as well as the name."""
assert _describe(descriptor(contract_name="MyContract"), SOURCE) == f"MyContract ({SOURCE})"


def test_the_source_alone_is_used_when_the_descriptor_names_nothing() -> None:
assert _describe(descriptor(), SOURCE) == str(SOURCE)


def test_neither_is_stated_rather_than_printing_none() -> None:
"""The old message read "file None", which named nothing at all."""
assert _describe(descriptor(), None) == "<unidentified>"


@pytest.mark.parametrize("source", [None, SOURCE])
def test_it_never_returns_none_as_text(source: HttpUrl | None) -> None:
assert "None" not in _describe(descriptor(), source)
Loading