From 5f8bbfefac167dce4c6515b074d5709959bee678 Mon Sep 17 00:00:00 2001 From: antazoey Date: Thu, 1 Aug 2024 11:43:01 -0500 Subject: [PATCH] chore: utilize flake8-pydantic (#2199) --- .pre-commit-config.yaml | 3 ++- setup.cfg | 1 + setup.py | 3 ++- src/ape/api/config.py | 4 +++- src/ape/api/projects.py | 2 +- src/ape/api/providers.py | 2 +- src/ape/api/transactions.py | 12 ++++++------ src/ape_ethereum/ecosystem.py | 6 +++--- src/ape_ethereum/transactions.py | 24 ++++++++++++------------ tests/functional/test_transaction.py | 4 ++-- tests/integration/cli/test_test.py | 6 +++--- 11 files changed, 36 insertions(+), 31 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2b98f5abcf..ca5b629243 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,9 +19,10 @@ repos: rev: 7.1.0 hooks: - id: flake8 + additional_dependencies: [flake8-breakpoint, flake8-print, flake8-pydantic] - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.11.0 + rev: v1.11.1 hooks: - id: mypy additional_dependencies: [ diff --git a/setup.cfg b/setup.cfg index f455fce233..3272b9ceeb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -7,6 +7,7 @@ exclude = build .eggs tests/integration/cli/projects +ignore = E704,W503,PYD002 per-file-ignores = # Need signal handler before imports src/ape/__init__.py: E402 diff --git a/setup.py b/setup.py index e8f523bd78..67bdef3b43 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ ], "lint": [ "black>=24.4.2,<25", # Auto-formatter and linter - "mypy>=1.11.0,<2", # Static type analyzer + "mypy>=1.11.1,<2", # Static type analyzer "types-PyYAML", # Needed due to mypy typeshed "types-requests", # Needed due to mypy typeshed "types-setuptools", # Needed due to mypy typeshed @@ -33,6 +33,7 @@ "flake8>=7.1.0,<8", # Style linter "flake8-breakpoint>=1.1.0,<2", # Detect breakpoints left in code "flake8-print>=4.0.1,<5", # Detect print statements left in code + "flake8-pydantic", # For detecting issues with Pydantic models "isort>=5.13.2,<6", # Import sorting linter "mdformat>=0.7.17", # Auto-formatter for markdown "mdformat-gfm>=0.3.5", # Needed for formatting GitHub-flavored markdown diff --git a/src/ape/api/config.py b/src/ape/api/config.py index 1fb0427ca9..7df4a4b669 100644 --- a/src/ape/api/config.py +++ b/src/ape/api/config.py @@ -310,7 +310,9 @@ def __init__(self, *args, **kwargs): Note: The actual dependency classes are decoded later. """ - deployment_data: dict[str, dict[str, list[DeploymentConfig]]] = Field({}, alias="deployments") + deployment_data: dict[str, dict[str, list[DeploymentConfig]]] = Field( + default_factory=dict, alias="deployments" + ) """ Data for deployed contracts from the project. """ diff --git a/src/ape/api/projects.py b/src/ape/api/projects.py index 86aa4ed5d6..9017c07149 100644 --- a/src/ape/api/projects.py +++ b/src/ape/api/projects.py @@ -18,7 +18,7 @@ class DependencyAPI(BaseInterfaceModel): The package-name of the dependency. """ - config_override: dict = Field({}, repr=False) + config_override: dict = Field(default_factory=dict, repr=False) """ Set different config than what Ape can deduce. """ diff --git a/src/ape/api/providers.py b/src/ape/api/providers.py index cc2473e753..12d772bf51 100644 --- a/src/ape/api/providers.py +++ b/src/ape/api/providers.py @@ -73,7 +73,7 @@ class BlockAPI(BaseInterfaceModel): The preceeding block's hash. """ parent_hash: Any = Field( - EMPTY_BYTES32, alias="parentHash" + default=EMPTY_BYTES32, alias="parentHash" ) # NOTE: genesis block has no parent hash """ diff --git a/src/ape/api/transactions.py b/src/ape/api/transactions.py index f9f55e18ea..0bfb91321c 100644 --- a/src/ape/api/transactions.py +++ b/src/ape/api/transactions.py @@ -51,10 +51,10 @@ class TransactionAPI(BaseInterfaceModel): such as typed-transactions from `EIP-1559 `__. """ - chain_id: Optional[int] = Field(0, alias="chainId") - receiver: Optional[AddressType] = Field(None, alias="to") - sender: Optional[AddressType] = Field(None, alias="from") - gas_limit: Optional[int] = Field(None, alias="gas") + chain_id: Optional[int] = Field(default=0, alias="chainId") + receiver: Optional[AddressType] = Field(default=None, alias="to") + sender: Optional[AddressType] = Field(default=None, alias="from") + gas_limit: Optional[int] = Field(default=None, alias="gas") nonce: Optional[int] = None # NOTE: `Optional` only to denote using default behavior value: int = 0 data: HexBytes = HexBytes("") @@ -63,9 +63,9 @@ class TransactionAPI(BaseInterfaceModel): max_priority_fee: Optional[int] = None # If left as None, will get set to the network's default required confirmations. - required_confirmations: Optional[int] = Field(None, exclude=True) + required_confirmations: Optional[int] = Field(default=None, exclude=True) - signature: Optional[TransactionSignature] = Field(None, exclude=True) + signature: Optional[TransactionSignature] = Field(default=None, exclude=True) model_config = ConfigDict(populate_by_name=True) diff --git a/src/ape_ethereum/ecosystem.py b/src/ape_ethereum/ecosystem.py index 121643032a..12efbe886e 100644 --- a/src/ape_ethereum/ecosystem.py +++ b/src/ape_ethereum/ecosystem.py @@ -330,15 +330,15 @@ class Block(BlockAPI): gas_limit: int = Field(alias="gasLimit") gas_used: int = Field(alias="gasUsed") - base_fee: int = Field(0, alias="baseFeePerGas") + base_fee: int = Field(default=0, alias="baseFeePerGas") difficulty: int = 0 - total_difficulty: int = Field(0, alias="totalDifficulty") + total_difficulty: int = Field(default=0, alias="totalDifficulty") uncles: list[HexBytes] = [] # Type re-declares. hash: Optional[HexBytes] = None parent_hash: HexBytes = Field( - EMPTY_BYTES32, alias="parentHash" + default=EMPTY_BYTES32, alias="parentHash" ) # NOTE: genesis block has no parent hash @field_validator( diff --git a/src/ape_ethereum/transactions.py b/src/ape_ethereum/transactions.py index bbae8ff9d3..4ecbf59a33 100644 --- a/src/ape_ethereum/transactions.py +++ b/src/ape_ethereum/transactions.py @@ -115,10 +115,10 @@ class StaticFeeTransaction(BaseTransaction): Transactions that are pre-EIP-1559 and use the ``gasPrice`` field. """ - gas_price: Optional[int] = Field(None, alias="gasPrice") - max_priority_fee: Optional[int] = Field(None, exclude=True) # type: ignore - type: int = Field(TransactionType.STATIC.value, exclude=True) - max_fee: Optional[int] = Field(None, exclude=True) # type: ignore + gas_price: Optional[int] = Field(default=None, alias="gasPrice") + max_priority_fee: Optional[int] = Field(default=None, exclude=True) # type: ignore + type: int = Field(default=TransactionType.STATIC.value, exclude=True) + max_fee: Optional[int] = Field(default=None, exclude=True) # type: ignore @model_validator(mode="before") @classmethod @@ -136,8 +136,8 @@ class AccessListTransaction(StaticFeeTransaction): transactions are similar to legacy transaction with an added access list functionality. """ - gas_price: Optional[int] = Field(None, alias="gasPrice") - type: int = Field(TransactionType.ACCESS_LIST.value) + gas_price: Optional[int] = Field(default=None, alias="gasPrice") + type: int = TransactionType.ACCESS_LIST.value access_list: list[AccessList] = Field(default_factory=list, alias="accessList") @field_validator("type") @@ -152,9 +152,9 @@ class DynamicFeeTransaction(BaseTransaction): and ``maxPriorityFeePerGas`` fields. """ - max_priority_fee: Optional[int] = Field(None, alias="maxPriorityFeePerGas") # type: ignore - max_fee: Optional[int] = Field(None, alias="maxFeePerGas") # type: ignore - type: int = Field(TransactionType.DYNAMIC.value) + max_priority_fee: Optional[int] = Field(default=None, alias="maxPriorityFeePerGas") + max_fee: Optional[int] = Field(default=None, alias="maxFeePerGas") + type: int = TransactionType.DYNAMIC.value access_list: list[AccessList] = Field(default_factory=list, alias="accessList") @field_validator("type") @@ -168,13 +168,13 @@ class SharedBlobTransaction(DynamicFeeTransaction): `EIP-4844 `__ transactions. """ - max_fee_per_blob_gas: int = Field(0, alias="maxFeePerBlobGas") - blob_versioned_hashes: list[HexBytes] = Field([], alias="blobVersionedHashes") + max_fee_per_blob_gas: int = Field(default=0, alias="maxFeePerBlobGas") + blob_versioned_hashes: list[HexBytes] = Field(default_factory=list, alias="blobVersionedHashes") """ Overridden because EIP-4844 states it cannot be nil. """ - receiver: AddressType = Field(ZERO_ADDRESS, alias="to") + receiver: AddressType = Field(default=ZERO_ADDRESS, alias="to") @field_validator("max_fee_per_blob_gas", mode="before") @classmethod diff --git a/tests/functional/test_transaction.py b/tests/functional/test_transaction.py index b01c70172f..a4b75f81dc 100644 --- a/tests/functional/test_transaction.py +++ b/tests/functional/test_transaction.py @@ -264,7 +264,7 @@ def test_data_when_contains_whitespace(): def test_model_dump_excludes_none_values(): - txn = StaticFeeTransaction() + txn = StaticFeeTransaction(sender=None) txn.value = 1000000 actual = txn.model_dump() assert "value" in actual @@ -285,7 +285,7 @@ def test_model_dump_access_list(): ], } ] - txn = AccessListTransaction(access_list=access_list) + txn = AccessListTransaction(access_list=access_list, sender=None) actual = txn.model_dump(exclude_none=True, by_alias=True) assert actual is not None diff --git a/tests/integration/cli/test_test.py b/tests/integration/cli/test_test.py index cbe5d20e0a..3be6580698 100644 --- a/tests/integration/cli/test_test.py +++ b/tests/integration/cli/test_test.py @@ -178,7 +178,7 @@ def test_test(setup_pytester, integ_project, pytester, eth_tester_provider): from ape.logging import logger logger.set_level("DEBUG") - result = pytester.runpytest_subprocess(timeout=30) + result = pytester.runpytest_subprocess(timeout=120) try: result.assert_outcomes(passed=passed, failed=failed), "\n".join(result.outlines) except ValueError: @@ -189,7 +189,7 @@ def test_test(setup_pytester, integ_project, pytester, eth_tester_provider): def test_uncaught_txn_err(setup_pytester, integ_project, pytester, eth_tester_provider): _ = eth_tester_provider # Ensure using EthTester for this test. setup_pytester(integ_project) - result = pytester.runpytest_subprocess(timeout=30) + result = pytester.runpytest_subprocess(timeout=120) expected = """ contract_in_test.setNumber(5, sender=owner) E ape.exceptions.ContractLogicError: Transaction failed. @@ -280,7 +280,7 @@ def test_gas_when_estimating(geth_provider, setup_pytester, integ_project, pytes geth_account.transfer(geth_account, "1 wei") # Force a clean block. with integ_project.temp_config(**cfg): passed, failed = setup_pytester(integ_project) - result = pytester.runpytest_subprocess(timeout=30) + result = pytester.runpytest_subprocess(timeout=120) run_gas_test(result, passed, failed)