Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: SourceID and ContractName types #115

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
4 changes: 3 additions & 1 deletion ethpm_types/abi.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ def signature(self) -> str:


class BaseABI(BaseModel):
...
"""
A base ABI.
"""
Comment on lines +97 to +99
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this note?



class ConstructorABI(BaseABI):
Expand Down
5 changes: 3 additions & 2 deletions ethpm_types/contract_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from ethpm_types.ast import ASTNode
from ethpm_types.base import BaseModel
from ethpm_types.sourcemap import PCMap, SourceMap
from ethpm_types.types import ContractName, SourceId

ABI_W_SELECTOR_T = Union[ConstructorABI, MethodABI, EventABI, StructABI, ErrorABI]
"""ABI types with selectors"""
Expand Down Expand Up @@ -245,13 +246,13 @@ class ContractType(BaseModel):
then ``MyContract`` would be the type.
"""

name: Optional[str] = Field(None, alias="contractName")
name: Optional[ContractName] = Field(None, alias="contractName")
"""
The name of the contract type. The field is optional if ``ContractAlias``
is the same as ``ContractName``.
"""

source_id: Optional[str] = Field(None, alias="sourceId")
source_id: Optional[SourceId] = Field(None, alias="sourceId")
"""
The global source identifier for the source file from which this contract type was generated.
"""
Expand Down
12 changes: 7 additions & 5 deletions ethpm_types/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from ethpm_types.base import BaseModel
from ethpm_types.contract_type import ContractInstance, ContractType
from ethpm_types.source import Compiler, Source
from ethpm_types.types import ContractName, SourceId
from ethpm_types.utils import Algorithm

ALPHABET = set("abcdefghijklmnopqrstuvwxyz")
Expand Down Expand Up @@ -112,13 +113,13 @@ class PackageManifest(BaseModel):
``meta``.
"""

sources: Optional[Dict[str, Source]] = None
sources: Optional[Dict[SourceId, Source]] = None
"""
The sources field defines a source tree that should comprise the full source tree
necessary to recompile the contracts contained in this release.
"""

contract_types: Optional[Dict[str, ContractType]] = Field(None, alias="contractTypes")
contract_types: Optional[Dict[ContractName, ContractType]] = Field(None, alias="contractTypes")
"""
:class:`~ethpm_types.contract_type.ContractType` objects that have been included
in this release.
Expand Down Expand Up @@ -225,15 +226,16 @@ def __getattr__(self, attr_name: str):
return self.__getattribute__(attr_name)
except AttributeError:
# Check if contract type name.
if contract_type := self.get_contract_type(attr_name):
contract_name = ContractName(attr_name)
if contract_type := self.get_contract_type(contract_name):
return contract_type

# NOTE: **must** raise `AttributeError` or return here, or else Python breaks
raise AttributeError(
f"{self.__class__.__name__} has no attribute or contract type named '{attr_name}'."
)

def get_contract_type(self, name: str) -> Optional[ContractType]:
def get_contract_type(self, name: ContractName) -> Optional[ContractType]:
"""
Get a contract type by name, if it exists. Else, returns ``None``.

Expand Down Expand Up @@ -325,7 +327,7 @@ def get_contract_compiler(self, contract_type_name: str) -> Optional[Compiler]:
Optional[`~ethpm_types.source.Compiler`]
"""
for compiler in self.compilers or []:
if contract_type_name in (compiler.contractTypes or []):
if contract_type_name in (compiler.contract_types or []):
return compiler

return None
Expand Down
15 changes: 7 additions & 8 deletions ethpm_types/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
import requests
from cid import make_cid # type: ignore
from eth_pydantic_types import HexBytes, HexStr
from pydantic import AnyUrl, RootModel, field_validator, model_validator
from pydantic import AnyUrl, Field, RootModel, field_validator, model_validator
from pydantic_core import PydanticCustomError

from ethpm_types.ast import ASTClassification, ASTNode, SourceLocation
from ethpm_types.base import BaseModel
from ethpm_types.contract_type import ContractType
from ethpm_types.sourcemap import PCMap
from ethpm_types.types import ContractName, SourceId
from ethpm_types.utils import (
CONTENT_ADDRESSED_SCHEMES,
Algorithm,
Expand Down Expand Up @@ -38,7 +39,7 @@ class Compiler(BaseModel):
[Compiler Input and Output Description](https://docs.soliditylang.org/en/latest/using-the-compiler.html#compiler-input-and-output-json-description).
""" # noqa: E501

contractTypes: Optional[List[str]] = None
contract_types: Optional[List[ContractName]] = Field(None, alias="contractTypes")
"""
A list of the contract type names in this package
that used this compiler to generate its outputs.
Expand Down Expand Up @@ -205,19 +206,17 @@ class Source(BaseModel):
license: Optional[str] = None
"""The type of license associated with this source file."""

references: Optional[List[str]] = None
references: Optional[List[SourceId]] = None
"""
List of `Source` objects that depend on this object.
**NOTE**: Not a part of canonical EIP-2678 spec.
"""
# TODO: Add `SourceId` type and use instead of `str`

imports: Optional[List[str]] = None
imports: Optional[List[SourceId]] = None
"""
List of source objects that this object depends on.
**NOTE**: Not a part of canonical EIP-2678 spec.
"""
# TODO: Add `SourceId` type and use instead of `str`

@model_validator(mode="before")
def validate_model(cls, model):
Expand Down Expand Up @@ -618,7 +617,7 @@ def create(cls, contract_type: ContractType, source: Source, base_path: Optional
return ContractSource(contract_type=contract_type, source=source, source_path=source_path)

@property
def source_id(self) -> str:
def source_id(self) -> SourceId:
"""The contract type source ID."""
return validate_source_id(self.contract_type)

Expand Down Expand Up @@ -762,7 +761,7 @@ def _strip_function(signature_lines: List[str]) -> str:
return name.rstrip(":{ \n")


def validate_source_id(contract_type: ContractType) -> str:
def validate_source_id(contract_type: ContractType) -> SourceId:
"""
A validator used by :class:`~ethpm_types.source.ContractSource`
to ensure the given :class:`~ethpm_types.contract_type.ContractType`
Expand Down
11 changes: 11 additions & 0 deletions ethpm_types/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from typing import NewType

"""
The name of a contract type.
"""
ContractName = NewType("ContractName", str)

"""
A source identifier.
"""
SourceId = NewType("SourceId", str)
Loading