diff --git a/.circleci/config.yml b/.circleci/config.yml index 5df3f2bc3e..1cd4058c40 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -168,6 +168,37 @@ jobs: environment: TOXENV: py37-lint + py38-core: + <<: *common + docker: + - image: circleci/python:3.8 + environment: + TOXENV: py38-core + py38-database: + <<: *common + docker: + - image: circleci/python:3.8 + environment: + TOXENV: py38-database + py38-transactions: + <<: *common + docker: + - image: circleci/python:3.8 + environment: + TOXENV: py38-transactions + py38-vm: + <<: *common + docker: + - image: circleci/python:3.8 + environment: + TOXENV: py38-vm + py38-lint: + <<: *common + docker: + - image: circleci/python:3.8 + environment: + TOXENV: py38-lint + workflows: version: 2 test: @@ -184,12 +215,17 @@ workflows: - py36-native-blockchain-transition - py36-vm - py37-vm + - py38-vm - py36-core - py37-core + - py38-core - py36-transactions - py37-transactions + - py38-transactions - py36-database - py37-database + - py38-database - py36-docs - py36-lint - py37-lint + - py38-lint diff --git a/eth/_utils/transactions.py b/eth/_utils/transactions.py index 4096495c05..cc290d2e4c 100644 --- a/eth/_utils/transactions.py +++ b/eth/_utils/transactions.py @@ -136,8 +136,8 @@ def calculate_intrinsic_gas( else: create_cost = 0 return ( - gas_schedule.gas_tx + - num_zero_bytes * gas_schedule.gas_txdatazero + - num_non_zero_bytes * gas_schedule.gas_txdatanonzero + - create_cost + gas_schedule.gas_tx + + num_zero_bytes * gas_schedule.gas_txdatazero + + num_non_zero_bytes * gas_schedule.gas_txdatanonzero + + create_cost ) diff --git a/eth/abc.py b/eth/abc.py index c2d70bc60e..8f43d8d960 100644 --- a/eth/abc.py +++ b/eth/abc.py @@ -20,7 +20,6 @@ TypeVar, Union, ) -from uuid import UUID import rlp @@ -886,9 +885,9 @@ def __call__(self, computation: 'ComputationAPI') -> None: def as_opcode(cls: Type[T], logic_fn: Callable[['ComputationAPI'], None], mnemonic: str, - gas_cost: int) -> Type[T]: + gas_cost: int) -> T: """ - Class factory method for turning vanilla functions into Opcode classes. + Class factory method for turning vanilla functions into Opcodes. """ ... @@ -1769,6 +1768,16 @@ def state_root(self) -> Hash32: """ ... + @state_root.setter + def state_root(self, value: Hash32) -> None: + """ + Force-set the state root hash. + """ + # See: https://github.com/python/mypy/issues/4165 + # Since we can't also decorate this with abstract method we want to be + # sure that the setter doesn't actually get used as a noop. + raise NotImplementedError + @abstractmethod def has_root(self, state_root: bytes) -> bool: """ @@ -1935,6 +1944,22 @@ def commit(self, checkpoint: JournalDBCheckpoint) -> None: """ ... + @abstractmethod + def lock_changes(self) -> None: + """ + Locks in changes across all accounts' storage databases. + + This is typically used at the end of a transaction, to make sure that + a revert doesn't roll back through the previous transaction, and to + be able to look up the "original" value of any account storage, where + "original" is the beginning of a transaction (instead of the beginning + of a block). + + See :meth:`eth.abc.AccountStorageDatabaseAPI.lock_changes` for + what is called on each account's storage database. + """ + ... + @abstractmethod def make_state_root(self) -> Hash32: """ @@ -2275,7 +2300,7 @@ def account_is_empty(self, address: Address) -> bool: # Access self._chaindb # @abstractmethod - def snapshot(self) -> Tuple[Hash32, UUID]: + def snapshot(self) -> Tuple[Hash32, JournalDBCheckpoint]: """ Perform a full snapshot of the current state. @@ -2285,14 +2310,14 @@ def snapshot(self) -> Tuple[Hash32, UUID]: ... @abstractmethod - def revert(self, snapshot: Tuple[Hash32, UUID]) -> None: + def revert(self, snapshot: Tuple[Hash32, JournalDBCheckpoint]) -> None: """ Revert the VM to the state at the snapshot """ ... @abstractmethod - def commit(self, snapshot: Tuple[Hash32, UUID]) -> None: + def commit(self, snapshot: Tuple[Hash32, JournalDBCheckpoint]) -> None: """ Commit the journal to the point where the snapshot was taken. This merges in any changes that were recorded since the snapshot. @@ -2481,6 +2506,7 @@ class VirtualMachineAPI(ConfigurableAPI): def __init__(self, header: BlockHeaderAPI, chaindb: ChainDatabaseAPI, + chain_context: ChainContextAPI, consensus_context: ConsensusContextAPI) -> None: """ Initialize the virtual machine. diff --git a/eth/chains/base.py b/eth/chains/base.py index f0c2227eaf..99a441d9e5 100644 --- a/eth/chains/base.py +++ b/eth/chains/base.py @@ -244,8 +244,8 @@ def from_genesis(cls, # the computed state from the initialized state database. raise ValidationError( "The provided genesis state root does not match the computed " - f"genesis state root. Got {state.state_root}. " - f"Expected {genesis_params['state_root']}" + f"genesis state root. Got {state.state_root!r}. " + f"Expected {genesis_params['state_root']!r}" ) genesis_header = BlockHeader(**genesis_params) @@ -463,8 +463,8 @@ def import_block(self, except HeaderNotFound: raise ValidationError( f"Attempt to import block #{block.number}. " - f"Cannot import block {block.hash} before importing " - f"its parent block at {block.header.parent_hash}" + f"Cannot import block {block.hash!r} before importing " + f"its parent block at {block.header.parent_hash!r}" ) base_header_for_import = self.create_header_from_parent(parent_header) diff --git a/eth/consensus/clique/_utils.py b/eth/consensus/clique/_utils.py index be39abb9be..50f62c99a2 100644 --- a/eth/consensus/clique/_utils.py +++ b/eth/consensus/clique/_utils.py @@ -139,10 +139,10 @@ def validate_header_integrity(header: BlockHeaderAPI, epoch_length: int) -> None ) if header.nonce != NONCE_AUTH and header.nonce != NONCE_DROP: - raise ValidationError(f"Invalid nonce: {header.nonce}") + raise ValidationError(f"Invalid nonce: {header.nonce!r}") if at_checkpoint and header.nonce != NONCE_DROP: - raise ValidationError(f"Invalid checkpoint nonce: {header.nonce}") + raise ValidationError(f"Invalid checkpoint nonce: {header.nonce!r}") if len(header.extra_data) < VANITY_LENGTH: raise ValidationError("Missing vanity bytes in extra data") @@ -159,7 +159,7 @@ def validate_header_integrity(header: BlockHeaderAPI, epoch_length: int) -> None raise ValidationError("Checkpoint header must contain list of signers") if header.mix_hash != ZERO_HASH32: - raise ValidationError(f"Invalid mix hash: {header.mix_hash}") + raise ValidationError(f"Invalid mix hash: {header.mix_hash!r}") if header.uncles_hash != EMPTY_UNCLE_HASH: raise ValidationError(f"Invalid uncle hash: {header.uncle_hash}") diff --git a/eth/consensus/clique/datatypes.py b/eth/consensus/clique/datatypes.py index a0a64dc245..554d1e0c03 100644 --- a/eth/consensus/clique/datatypes.py +++ b/eth/consensus/clique/datatypes.py @@ -46,7 +46,7 @@ def validate_for(self, if not signer_is_kicked and not signer_is_nominated: raise ValidationError( "Must either kick an existing signer or nominate a new signer" - f"Subject: {subject} Current signers: {signers}" + f"Subject: {subject!r} Current signers: {signers}" ) diff --git a/eth/consensus/clique/snapshot_manager.py b/eth/consensus/clique/snapshot_manager.py index cc0904133c..cb66d83a4e 100644 --- a/eth/consensus/clique/snapshot_manager.py +++ b/eth/consensus/clique/snapshot_manager.py @@ -182,7 +182,7 @@ def create_snapshot_for(self, try: new_snapshot = self.get_snapshot( current_header.block_number, current_header.parent_hash) - except SnapshotNotFound as e: + except SnapshotNotFound: current_header = self._lookup_header(current_header.parent_hash, cached_parents) if is_checkpoint(current_header.block_number, self._epoch_length): @@ -225,16 +225,16 @@ def get_snapshot(self, block_number: int, block_hash: Hash32) -> Snapshot: # Otherwise, we can retrieve it on the fly header = self._chain_db.get_block_header_by_hash(block_hash) except HeaderNotFound: - raise SnapshotNotFound(f"Can not get snapshot for {block_hash} at {block_number}") + raise SnapshotNotFound(f"Can not get snapshot for {block_hash!r} at {block_number}") else: if header.block_number != block_number: raise SnapshotNotFound( - f"Can not get snapshot for {block_hash} at {block_number}" + f"Can not get snapshot for {block_hash!r} at {block_number}" ) else: return self._create_snapshot_from_checkpoint_header(header) - raise SnapshotNotFound(f"Can not get snapshot for {block_hash} at {block_number}") + raise SnapshotNotFound(f"Can not get snapshot for {block_hash!r} at {block_number}") def add_snapshot(self, mutable_snapshot: MutableSnapshot) -> Snapshot: """ @@ -261,8 +261,8 @@ def get_snapshot_from_db(self, block_hash: Hash32) -> Snapshot: encoded_key = self._chain_db.db[key] except KeyError as e: raise SnapshotNotFound( - f"Can not get on-disk snapshot for {block_hash}" - ) + f"Can not get on-disk snapshot for {block_hash!r}" + ) from e else: return decode_snapshot(encoded_key) diff --git a/eth/db/chain.py b/eth/db/chain.py index c10e78f7de..86748d933b 100644 --- a/eth/db/chain.py +++ b/eth/db/chain.py @@ -86,7 +86,7 @@ def get_block_uncles(self, uncles_hash: Hash32) -> Tuple[BlockHeaderAPI, ...]: encoded_uncles = self.db[uncles_hash] except KeyError: raise HeaderNotFound( - f"No uncles found for hash {uncles_hash}" + f"No uncles found for hash {uncles_hash!r}" ) else: return tuple(rlp.decode(encoded_uncles, sedes=rlp.sedes.CountableList(BlockHeader))) @@ -141,16 +141,16 @@ def persist_unexecuted_block(self, if tx_root_hash != block.header.transaction_root: raise ValidationError( - f"Block's transaction_root ({block.header.transaction_root}) " - f"does not match expected value: {tx_root_hash}" + f"Block's transaction_root ({block.header.transaction_root!r}) " + f"does not match expected value: {tx_root_hash!r}" ) receipt_root_hash, receipt_kv_nodes = make_trie_root_and_nodes(receipts) if receipt_root_hash != block.header.receipt_root: raise ValidationError( - f"Block's receipt_root ({block.header.receipt_root}) " - f"does not match expected value: {receipt_root_hash}" + f"Block's receipt_root ({block.header.receipt_root!r}) " + f"does not match expected value: {receipt_root_hash!r}" ) with self.db.atomic_batch() as db: diff --git a/eth/db/header.py b/eth/db/header.py index 33023ef0a7..904d814313 100644 --- a/eth/db/header.py +++ b/eth/db/header.py @@ -79,22 +79,23 @@ def _update_header_chain_gaps( cls, db: DatabaseAPI, persisted_header: BlockHeaderAPI, - base_gaps: ChainGaps = None) -> GapInfo: + base_gaps: ChainGaps = None + ) -> GapInfo: - # If we make many updates in a row, we can avoid reloading the integrity info by - # continuously caching it and providing it as a parameter to this API - if base_gaps is None: - base_gaps = cls._get_header_chain_gaps(db) + # If we make many updates in a row, we can avoid reloading the integrity info by + # continuously caching it and providing it as a parameter to this API + if base_gaps is None: + base_gaps = cls._get_header_chain_gaps(db) - gap_change, gaps = fill_gap(persisted_header.block_number, base_gaps) + gap_change, gaps = fill_gap(persisted_header.block_number, base_gaps) - if gap_change is not GapChange.NoChange: - db.set( - SchemaV1.make_header_chain_gaps_lookup_key(), - rlp.encode(gaps, sedes=chain_gaps) - ) + if gap_change is not GapChange.NoChange: + db.set( + SchemaV1.make_header_chain_gaps_lookup_key(), + rlp.encode(gaps, sedes=chain_gaps) + ) - return gap_change, gaps + return gap_change, gaps # # Canonical Chain API @@ -260,7 +261,7 @@ def _persist_checkpoint_header( # True parent should have already been canonicalized during # _set_as_canonical_chain_head() raise ValidationError( - f"Why was a non-matching parent header {parent_hash} left as canonical " + f"Why was a non-matching parent header {parent_hash!r} left as canonical " f"after _set_as_canonical_chain_head() and {true_parent} is available?" ) diff --git a/eth/precompiles/modexp.py b/eth/precompiles/modexp.py index 54168a1ebe..fb403bfc3b 100644 --- a/eth/precompiles/modexp.py +++ b/eth/precompiles/modexp.py @@ -34,8 +34,8 @@ def _compute_adjusted_exponent_length(exponent_length: int, else: first_32_bytes_as_int = big_endian_to_int(first_32_exponent_bytes) return ( - 8 * (exponent_length - 32) + - get_highest_bit_index(first_32_bytes_as_int) + 8 * (exponent_length - 32) + + get_highest_bit_index(first_32_bytes_as_int) ) @@ -78,9 +78,9 @@ def _compute_modexp_gas_fee(data: bytes) -> int: complexity = _compute_complexity(max(modulus_length, base_length)) gas_fee = ( - complexity * - max(adjusted_exponent_length, 1) // - constants.GAS_MOD_EXP_QUADRATIC_DENOMINATOR + complexity + * max(adjusted_exponent_length, 1) + // constants.GAS_MOD_EXP_QUADRATIC_DENOMINATOR ) return gas_fee diff --git a/eth/tools/fixtures/helpers.py b/eth/tools/fixtures/helpers.py index dc785a05fb..31fb55c425 100644 --- a/eth/tools/fixtures/helpers.py +++ b/eth/tools/fixtures/helpers.py @@ -76,13 +76,13 @@ def verify_state(expected_state: AccountState, state: StateAPI) -> None: if field == 'balance': error_messages.append( f"{to_normalized_address(account)}(balance) | " - f"Actual: {actual_value} | Expected: {expected_value} | " + f"Actual: {actual_value!r} | Expected: {expected_value!r} | " f"Delta: {cast(int, actual_value) - cast(int, expected_value)}" ) else: error_messages.append( f"{to_normalized_address(account)}({field}) | " - f"Actual: {actual_value} | Expected: {expected_value}" + f"Actual: {actual_value!r} | Expected: {expected_value!r}" ) raise AssertionError( f"State DB did not match expected state on {len(error_messages)} values:{new_line}" diff --git a/eth/validation.py b/eth/validation.py index 1c72600d3e..f1b7003b8b 100644 --- a/eth/validation.py +++ b/eth/validation.py @@ -111,7 +111,7 @@ def validate_lt(value: int, maximum: int, title: str="Value") -> None: def validate_canonical_address(value: Address, title: str="Value") -> None: if not isinstance(value, bytes) or not len(value) == 20: raise ValidationError( - f"{title} {value} is not a valid canonical address" + f"{title} {value!r} is not a valid canonical address" ) diff --git a/eth/vm/base.py b/eth/vm/base.py index 64df6f74a1..b073397e70 100644 --- a/eth/vm/base.py +++ b/eth/vm/base.py @@ -245,7 +245,7 @@ def apply_all_transactions( previous_header, transaction, ) - except EVMMissingData as exc: + except EVMMissingData: self.state.revert(snapshot) raise @@ -368,7 +368,7 @@ def finalize_block(self, block: BlockAPI) -> BlockAndMetaWitness: snapshot = self.state.snapshot() try: self._assign_block_rewards(block) - except EVMMissingData as exc: + except EVMMissingData: self.state.revert(snapshot) raise else: @@ -537,7 +537,7 @@ def validate_block(self, block: BlockAPI) -> None: if tx_root_hash != block.header.transaction_root: raise ValidationError( f"Block's transaction_root ({block.header.transaction_root}) " - f"does not match expected value: {tx_root_hash}" + f"does not match expected value: {tx_root_hash!r}" ) if len(block.uncles) > MAX_UNCLES: diff --git a/eth/vm/forks/byzantium/headers.py b/eth/vm/forks/byzantium/headers.py index 47116ff52d..1c76034e7a 100644 --- a/eth/vm/forks/byzantium/headers.py +++ b/eth/vm/forks/byzantium/headers.py @@ -50,8 +50,8 @@ def compute_difficulty( has_uncles = parent_header.uncles_hash != EMPTY_UNCLE_HASH adj_factor = max( ( - (2 if has_uncles else 1) - - ((timestamp - parent_timestamp) // BYZANTIUM_DIFFICULTY_ADJUSTMENT_CUTOFF) + (2 if has_uncles else 1) + - ((timestamp - parent_timestamp) // BYZANTIUM_DIFFICULTY_ADJUSTMENT_CUTOFF) ), -99, ) diff --git a/eth/vm/forks/frontier/validation.py b/eth/vm/forks/frontier/validation.py index f14ba2f3e9..6de5e7a150 100644 --- a/eth/vm/forks/frontier/validation.py +++ b/eth/vm/forks/frontier/validation.py @@ -17,7 +17,7 @@ def validate_frontier_transaction(state: StateAPI, if sender_balance < gas_cost: raise ValidationError( - f"Sender {transaction.sender} cannot afford txn gas " + f"Sender {transaction.sender!r} cannot afford txn gas " f"{gas_cost} with account balance {sender_balance}" ) diff --git a/eth/vm/forks/spurious_dragon/state.py b/eth/vm/forks/spurious_dragon/state.py index 8360eb7e31..802278b595 100644 --- a/eth/vm/forks/spurious_dragon/state.py +++ b/eth/vm/forks/spurious_dragon/state.py @@ -31,8 +31,8 @@ def finalize_computation(self, for account in touched_accounts: should_delete = ( - self.vm_state.account_exists(account) and - self.vm_state.account_is_empty(account) + self.vm_state.account_exists(account) + and self.vm_state.account_is_empty(account) ) if should_delete: self.vm_state.logger.debug2( diff --git a/eth/vm/logic/call.py b/eth/vm/logic/call.py index 3bf3f310a8..c4f8659670 100644 --- a/eth/vm/logic/call.py +++ b/eth/vm/logic/call.py @@ -365,8 +365,8 @@ def compute_msg_extra_gas(self, to: Address, value: int) -> int: account_is_dead = ( - not computation.state.account_exists(to) or - computation.state.account_is_empty(to) + not computation.state.account_exists(to) + or computation.state.account_is_empty(to) ) transfer_gas_fee = constants.GAS_CALLVALUE if value else 0 diff --git a/eth/vm/logic/system.py b/eth/vm/logic/system.py index dac56117f2..b42f43c60a 100644 --- a/eth/vm/logic/system.py +++ b/eth/vm/logic/system.py @@ -65,8 +65,8 @@ def selfdestruct_eip150(computation: ComputationAPI) -> None: def selfdestruct_eip161(computation: ComputationAPI) -> None: beneficiary = force_bytes_to_address(computation.stack_pop1_bytes()) is_dead = ( - not computation.state.account_exists(beneficiary) or - computation.state.account_is_empty(beneficiary) + not computation.state.account_exists(beneficiary) + or computation.state.account_is_empty(beneficiary) ) if is_dead and computation.state.get_balance(computation.msg.storage_address): computation.consume_gas( diff --git a/eth/vm/state.py b/eth/vm/state.py index 688f1d3dba..c3f2c2a167 100644 --- a/eth/vm/state.py +++ b/eth/vm/state.py @@ -4,7 +4,6 @@ Tuple, Type, ) -from uuid import UUID from eth_typing import ( Address, @@ -32,6 +31,7 @@ from eth.constants import ( MAX_PREV_HEADER_DEPTH, ) +from eth.typing import JournalDBCheckpoint from eth._utils.datatypes import ( Configurable, ) @@ -52,7 +52,7 @@ def __init__( self, db: AtomicDatabaseAPI, execution_context: ExecutionContextAPI, - state_root: bytes) -> None: + state_root: Hash32) -> None: self._db = db self.execution_context = execution_context self._account_db = self.get_account_db_class()(db, state_root) @@ -161,10 +161,10 @@ def account_is_empty(self, address: Address) -> bool: # # Access self._chaindb # - def snapshot(self) -> Tuple[Hash32, UUID]: + def snapshot(self) -> Tuple[Hash32, JournalDBCheckpoint]: return self.state_root, self._account_db.record() - def revert(self, snapshot: Tuple[Hash32, UUID]) -> None: + def revert(self, snapshot: Tuple[Hash32, JournalDBCheckpoint]) -> None: state_root, account_snapshot = snapshot # first revert the database state root. @@ -172,7 +172,7 @@ def revert(self, snapshot: Tuple[Hash32, UUID]) -> None: # now roll the underlying database back self._account_db.discard(account_snapshot) - def commit(self, snapshot: Tuple[Hash32, UUID]) -> None: + def commit(self, snapshot: Tuple[Hash32, JournalDBCheckpoint]) -> None: _, account_snapshot = snapshot self._account_db.commit(account_snapshot) @@ -188,9 +188,9 @@ def persist(self) -> MetaWitnessAPI: def get_ancestor_hash(self, block_number: int) -> Hash32: ancestor_depth = self.block_number - block_number - 1 is_ancestor_depth_out_of_range = ( - ancestor_depth >= MAX_PREV_HEADER_DEPTH or - ancestor_depth < 0 or - block_number < 0 + ancestor_depth >= MAX_PREV_HEADER_DEPTH + or ancestor_depth < 0 + or block_number < 0 ) if is_ancestor_depth_out_of_range: return Hash32(b'') diff --git a/newsfragments/1940.feature.rst b/newsfragments/1940.feature.rst new file mode 100644 index 0000000000..01369c98fa --- /dev/null +++ b/newsfragments/1940.feature.rst @@ -0,0 +1 @@ +Added support for Python 3.8. diff --git a/scripts/benchmark/run.py b/scripts/benchmark/run.py index 334a016da0..34c129ce48 100755 --- a/scripts/benchmark/run.py +++ b/scripts/benchmark/run.py @@ -50,12 +50,11 @@ HEADER = ( "\n" - "______ _ _ \n" - "| ___ \ | | | | \n" - "| |_/ / ___ _ __ ___| |__ _ __ ___ __ _ _ __| | __ \n" - "| ___ \/ _ \ '_ \ / __| '_ \| '_ ` _ \ / _` | '__| |/ / \n" - "| |_/ / __/ | | | (__| | | | | | | | | (_| | | | < \n" - "\____/ \___|_| |_|\___|_| |_|_| |_| |_|\__,_|_| |_|\_\\\n" + "██████  ███████ ███  ██  ██████ ██  ██ ███  ███  █████  ██████  ██  ██\n" + "██   ██ ██      ████  ██ ██      ██  ██ ████  ████ ██   ██ ██   ██ ██  ██ \n" + "██████  █████  ██ ██  ██ ██  ███████ ██ ████ ██ ███████ ██████  █████  \n" + "██   ██ ██     ██  ██ ██ ██  ██   ██ ██  ██  ██ ██   ██ ██   ██ ██  ██ \n" + "██████  ███████ ██   ████  ██████ ██  ██ ██      ██ ██  ██ ██  ██ ██  ██\n" ) diff --git a/setup.py b/setup.py index 378107e318..ae8e4057a2 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ "eth-bloom>=1.0.3,<2.0.0", "eth-keys>=0.2.1,<0.4.0", "eth-typing>=2.2.0,<3.0.0", - "eth-utils>=1.7.0,<2.0.0", + "eth-utils>=1.8.0,<2.0.0", "lru-dict>=1.1.6", "mypy_extensions>=0.4.1,<1.0.0", "py-ecc>=1.4.7,<5.0.0", @@ -23,10 +23,10 @@ # Installing these libraries may make the evm perform better than # using the default fallbacks though. 'eth-extra': [ - "coincurve>=10.0.0,<11.0.0", + "coincurve>=13.0.0,<14.0.0", "eth-hash[pysha3];implementation_name=='cpython'", "eth-hash[pycryptodome];implementation_name=='pypy'", - "plyvel>=1.0.5,<1.2.0", + "plyvel>=1.2.0,<2", ], 'test': [ "factory-boy==2.11.1", @@ -39,9 +39,9 @@ "pytest-xdist==1.31.0", ], 'lint': [ - "flake8==3.5.0", - "flake8-bugbear==18.8.0", - "mypy==0.701", + "flake8==3.8.2", + "flake8-bugbear==20.1.4", + "mypy==0.750", ], 'benchmark': [ "termcolor>=1.1.0,<2.0.0", diff --git a/tests/core/validation/test_eth1_validation.py b/tests/core/validation/test_eth1_validation.py index 520a799bad..b499ebaf64 100644 --- a/tests/core/validation/test_eth1_validation.py +++ b/tests/core/validation/test_eth1_validation.py @@ -271,7 +271,7 @@ def test_validate_multiple_of(value, multiple_of, is_valid): ) def test_validate_word(value, is_valid): if is_valid: - validate_word(value) + validate_word(value) else: with pytest.raises(ValidationError): validate_word(value) @@ -291,7 +291,7 @@ def test_validate_word(value, is_valid): ) def test_validate_uint256(value, is_valid): if is_valid: - validate_uint256(value) + validate_uint256(value) else: with pytest.raises(ValidationError): validate_uint256(value) @@ -344,7 +344,7 @@ def test_validate_stack_bytes(value, is_valid): ) def test_validate_lt_secpk1n(value, is_valid): if is_valid: - validate_lt_secpk1n(value) + validate_lt_secpk1n(value) else: with pytest.raises(ValidationError): validate_lt_secpk1n(value) @@ -362,7 +362,7 @@ def test_validate_lt_secpk1n(value, is_valid): ) def test_validate_lt_secpk1n2(value, is_valid): if is_valid: - validate_lt_secpk1n2(value) + validate_lt_secpk1n2(value) else: with pytest.raises(ValidationError): validate_lt_secpk1n2(value) @@ -404,7 +404,7 @@ def test_validate_block_number(block_number, is_valid): ) def test_validate_vm_block_numbers(vm_block_numbers, is_valid): if is_valid: - validate_vm_block_numbers(vm_block_numbers) + validate_vm_block_numbers(vm_block_numbers) else: with pytest.raises(ValidationError): validate_vm_block_numbers(vm_block_numbers) diff --git a/tests/core/vm/test_mainnet_dao_fork.py b/tests/core/vm/test_mainnet_dao_fork.py index 2d60273456..a6c7b9553b 100644 --- a/tests/core/vm/test_mainnet_dao_fork.py +++ b/tests/core/vm/test_mainnet_dao_fork.py @@ -289,4 +289,4 @@ def test_mainnet_dao_fork_header_validation(VM, header, previous_header, valid): except ValidationError: pass else: - assert False, "The invalid header %r must fail" % header + raise AssertionError("The invalid header %r must fail" % header) diff --git a/tests/core/vm/test_rewards.py b/tests/core/vm/test_rewards.py index 16234f723a..134321d744 100644 --- a/tests/core/vm/test_rewards.py +++ b/tests/core/vm/test_rewards.py @@ -78,9 +78,9 @@ def test_rewards(vm_fn, miner_1_balance, miner_2_balance): # We first test if the balance matches what we would determine # if we made all the API calls involved ourselves. - assert coinbase_balance == (vm.get_block_reward() * - TOTAL_BLOCKS_CANONICAL_CHAIN + - vm.get_nephew_reward()) + assert coinbase_balance == (vm.get_block_reward() + * TOTAL_BLOCKS_CANONICAL_CHAIN + + vm.get_nephew_reward()) assert other_miner_balance == vm.get_uncle_reward(block.number, uncle) # But we also ensure the balance matches the numbers that we calculated on paper @@ -181,9 +181,9 @@ def test_rewards_uncle_created_at_different_generations( # We first test if the balance matches what we would determine # if we made all the API calls involved ourselves. - assert coinbase_balance == (vm.get_block_reward() * - TOTAL_BLOCKS_CANONICAL_CHAIN + - vm.get_nephew_reward()) + assert coinbase_balance == (vm.get_block_reward() + * TOTAL_BLOCKS_CANONICAL_CHAIN + + vm.get_nephew_reward()) assert other_miner_balance == vm.get_uncle_reward(block.number, uncle) @@ -298,9 +298,9 @@ def test_rewards_nephew_uncle_different_vm( # We first test if the balance matches what we would determine # if we made all the API calls involved ourselves. assert coinbase_balance == ( - uncle_vm.get_block_reward() * 3 + - nephew_vm.get_block_reward() * (TOTAL_BLOCKS_CANONICAL_CHAIN - 3) + - vm.get_nephew_reward() + uncle_vm.get_block_reward() * 3 + + nephew_vm.get_block_reward() * (TOTAL_BLOCKS_CANONICAL_CHAIN - 3) + + vm.get_nephew_reward() ) assert other_miner_balance == vm.get_uncle_reward(block.number, uncle) diff --git a/tests/database/test_db_diff.py b/tests/database/test_db_diff.py index cd8e51a85f..cfa3bb06f3 100644 --- a/tests/database/test_db_diff.py +++ b/tests/database/test_db_diff.py @@ -61,7 +61,7 @@ def test_database_api_missing_key_retrieval(db): except DiffMissingError as exc: assert not exc.is_deleted else: - assert False, f"key should be missing, but was retrieved as {val}" + raise AssertionError(f"key should be missing, but was retrieved as {val}") def test_database_api_missing_key_for_deletion(db): @@ -73,7 +73,7 @@ def test_database_api_missing_key_for_deletion(db): except DiffMissingError as exc: assert exc.is_deleted else: - assert False, f"key should be missing, but was retrieved as {val}" + raise AssertionError(f"key should be missing, but was retrieved as {val}") def test_db_diff_equality(db): @@ -98,7 +98,7 @@ def test_database_api_deleted_key_for_deletion(db): except DiffMissingError as exc: assert exc.is_deleted else: - assert False, f"key should be missing, but was retrieved as {val}" + raise AssertionError(f"key should be missing, but was retrieved as {val}") @pytest.mark.parametrize( diff --git a/tests/json-fixtures/test_blockchain.py b/tests/json-fixtures/test_blockchain.py index 69794cc20c..493891e2f6 100644 --- a/tests/json-fixtures/test_blockchain.py +++ b/tests/json-fixtures/test_blockchain.py @@ -297,7 +297,7 @@ def test_blockchain_fixtures(fixture_data, fixture): else: try: apply_fixture_block_to_chain(block_fixture, chain) - except (TypeError, rlp.DecodingError, rlp.DeserializationError, ValidationError) as err: + except (TypeError, rlp.DecodingError, rlp.DeserializationError, ValidationError): # failure is expected on this bad block pass else: diff --git a/tests/json-fixtures/test_virtual_machine.py b/tests/json-fixtures/test_virtual_machine.py index 8a70e1a3ad..97c897c568 100644 --- a/tests/json-fixtures/test_virtual_machine.py +++ b/tests/json-fixtures/test_virtual_machine.py @@ -137,7 +137,7 @@ def vm_class(request): elif request.param == 'SpuriousDragon': pytest.skip('Only the Homestead VM rules are currently supported') else: - assert False, f"Unsupported VM: {request.param}" + raise AssertionError(f"Unsupported VM: {request.param}") def fixture_to_computation(fixture, code, vm): diff --git a/tox.ini b/tox.ini index 457a62af46..63a1cd897f 100644 --- a/tox.ini +++ b/tox.ini @@ -1,15 +1,23 @@ [tox] envlist= - py{36,37}-{core,database,transactions,vm} + py{36,37,38}-{core,database,transactions,vm} py36-benchmark py36-native-blockchain-{frontier,homestead,tangerine_whistle,spurious_dragon,byzantium,constantinople,petersburg,istanbul,metropolis,transition} - py{36,37}-lint + py{36,37,38}-lint py36-docs [flake8] max-line-length= 100 exclude= -ignore= +ignore = + # E252 missing whitespace around parameter equals + # Already used too much in the codebase at the point of introduction. + E252, + # W503 line break before binary operator + # It's either this or W504 (line break _after_ binary operator), pick your poison. + # W503 gets enabled when E252 gets ignored, see: + # https://github.com/ethereum/py-evm/pull/1940#discussion_r432606845 + W503 [testenv] usedevelop=True @@ -41,6 +49,7 @@ deps = basepython = py36: python3.6 py37: python3.7 + py38: python3.8 [testenv:py36-docs]