diff --git a/.circleci/config.yml b/.circleci/config.yml index f1a7bfccd1..169c3fa260 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -63,6 +63,7 @@ common: &common - ~/.local - ./eggs key: cache-v1-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "setup.py" }}-{{ checksum "tox.ini" }} + resource_class: xlarge jobs: docs: @@ -72,84 +73,84 @@ jobs: environment: TOXENV: docs - py39-native-blockchain-berlin: + py311-native-blockchain-berlin: <<: *common docker: - - image: cimg/python:3.9 + - image: cimg/python:3.11 environment: - TOXENV: py39-native-blockchain-berlin - py39-native-blockchain-byzantium: + TOXENV: py311-native-blockchain-berlin + py311-native-blockchain-byzantium: <<: *common docker: - - image: cimg/python:3.9 + - image: cimg/python:3.11 environment: - TOXENV: py39-native-blockchain-byzantium - py39-native-blockchain-constantinople: + TOXENV: py311-native-blockchain-byzantium + py311-native-blockchain-constantinople: <<: *common docker: - - image: cimg/python:3.9 + - image: cimg/python:3.11 environment: - TOXENV: py39-native-blockchain-constantinople - py39-native-blockchain-frontier: + TOXENV: py311-native-blockchain-constantinople + py311-native-blockchain-frontier: <<: *common docker: - - image: cimg/python:3.9 + - image: cimg/python:3.11 environment: - TOXENV: py39-native-blockchain-frontier - py39-native-blockchain-homestead: + TOXENV: py311-native-blockchain-frontier + py311-native-blockchain-homestead: <<: *common docker: - - image: cimg/python:3.9 + - image: cimg/python:3.11 environment: - TOXENV: py39-native-blockchain-homestead - py39-native-blockchain-istanbul: + TOXENV: py311-native-blockchain-homestead + py311-native-blockchain-istanbul: <<: *common docker: - - image: cimg/python:3.9 + - image: cimg/python:3.11 environment: - TOXENV: py39-native-blockchain-istanbul - py39-native-blockchain-london: + TOXENV: py311-native-blockchain-istanbul + py311-native-blockchain-london: <<: *common docker: - - image: cimg/python:3.9 + - image: cimg/python:3.11 environment: - TOXENV: py39-native-blockchain-london - py39-native-blockchain-merge: + TOXENV: py311-native-blockchain-london + py311-native-blockchain-merge: <<: *common docker: - - image: cimg/python:3.9 + - image: cimg/python:3.11 environment: - TOXENV: py39-native-blockchain-merge - py39-native-blockchain-petersburg: + TOXENV: py311-native-blockchain-merge + py311-native-blockchain-petersburg: <<: *common docker: - - image: cimg/python:3.9 + - image: cimg/python:3.11 environment: - TOXENV: py39-native-blockchain-petersburg - py39-native-blockchain-tangerine_whistle: + TOXENV: py311-native-blockchain-petersburg + py311-native-blockchain-tangerine_whistle: <<: *common docker: - - image: cimg/python:3.9 + - image: cimg/python:3.11 environment: - TOXENV: py39-native-blockchain-tangerine_whistle - py39-native-blockchain-spurious_dragon: + TOXENV: py311-native-blockchain-tangerine_whistle + py311-native-blockchain-spurious_dragon: <<: *common docker: - - image: cimg/python:3.9 + - image: cimg/python:3.11 environment: - TOXENV: py39-native-blockchain-spurious_dragon - py39-native-blockchain-transition: + TOXENV: py311-native-blockchain-spurious_dragon + py311-native-blockchain-transition: <<: *common docker: - - image: cimg/python:3.9 + - image: cimg/python:3.11 environment: - TOXENV: py39-native-blockchain-transition - py39-native-blockchain-shanghai: + TOXENV: py311-native-blockchain-transition + py311-native-blockchain-shanghai: <<: *common docker: - - image: cimg/python:3.9 + - image: cimg/python:3.11 environment: - TOXENV: py39-native-blockchain-shanghai + TOXENV: py311-native-blockchain-shanghai py37-core: <<: *common @@ -256,38 +257,124 @@ jobs: environment: TOXENV: py39-lint + py310-core: + <<: *common + docker: + - image: cimg/python:3.10 + environment: + TOXENV: py310-core + py310-database: + <<: *common + docker: + - image: cimg/python:3.10 + environment: + TOXENV: py310-database + py310-difficulty: + <<: *common + docker: + - image: cimg/python:3.10 + environment: + TOXENV: py310-difficulty + py310-transactions: + <<: *common + docker: + - image: cimg/python:3.10 + environment: + TOXENV: py310-transactions + py310-vm: + <<: *common + docker: + - image: cimg/python:3.10 + environment: + TOXENV: py310-vm + py310-lint: + <<: *common + docker: + - image: cimg/python:3.10 + environment: + TOXENV: py310-lint + + py311-core: + <<: *common + docker: + - image: cimg/python:3.11 + environment: + TOXENV: py311-core + py311-database: + <<: *common + docker: + - image: cimg/python:3.11 + environment: + TOXENV: py311-database + py311-difficulty: + <<: *common + docker: + - image: cimg/python:3.11 + environment: + TOXENV: py311-difficulty + py311-transactions: + <<: *common + docker: + - image: cimg/python:3.11 + environment: + TOXENV: py311-transactions + py311-vm: + <<: *common + docker: + - image: cimg/python:3.11 + environment: + TOXENV: py311-vm + py311-lint: + <<: *common + docker: + - image: cimg/python:3.11 + environment: + TOXENV: py311-lint + workflows: version: 2 test: jobs: - docs - - py39-native-blockchain-berlin - - py39-native-blockchain-byzantium - - py39-native-blockchain-constantinople - - py39-native-blockchain-frontier - - py39-native-blockchain-homestead - - py39-native-blockchain-istanbul - - py39-native-blockchain-london - - py39-native-blockchain-merge - - py39-native-blockchain-petersburg - - py39-native-blockchain-tangerine_whistle - - py39-native-blockchain-spurious_dragon - - py39-native-blockchain-transition - - py39-native-blockchain-shanghai + - py311-native-blockchain-shanghai + - py311-native-blockchain-merge + - py311-native-blockchain-london + - py311-native-blockchain-berlin + - py311-native-blockchain-byzantium + - py311-native-blockchain-constantinople + - py311-native-blockchain-frontier + - py311-native-blockchain-homestead + - py311-native-blockchain-istanbul + - py311-native-blockchain-petersburg + - py311-native-blockchain-tangerine_whistle + - py311-native-blockchain-spurious_dragon + - py311-native-blockchain-transition - py37-vm - py38-vm - py39-vm + - py310-vm + - py311-vm - py37-core - py38-core - py39-core + - py310-core + - py311-core - py37-transactions - py38-transactions - py39-transactions + - py310-transactions + - py311-transactions - py37-difficulty - py38-difficulty - py39-difficulty + - py310-difficulty + - py311-difficulty - py37-database - py38-database - py39-database + - py310-database + - py311-database - py38-lint - py39-lint + - py310-lint + - py311-lint diff --git a/docs/api/db/api.db.backends.rst b/docs/api/db/api.db.backends.rst index ef65a9ecb8..bc2459b9e5 100644 --- a/docs/api/db/api.db.backends.rst +++ b/docs/api/db/api.db.backends.rst @@ -7,12 +7,6 @@ BaseDB .. autoclass:: eth.db.backends.base.BaseDB :members: -LevelDB -------- - -.. autoclass:: eth.db.backends.level.LevelDB - :members: - MemoryDB -------- diff --git a/eth/db/backends/level.py b/eth/db/backends/level.py deleted file mode 100644 index 1bc510d586..0000000000 --- a/eth/db/backends/level.py +++ /dev/null @@ -1,156 +0,0 @@ -from contextlib import ( - contextmanager, -) -import logging -from pathlib import ( - Path, -) -from typing import ( - TYPE_CHECKING, - Iterator, -) - -from eth_utils import ( - ValidationError, -) - -from eth._warnings import ( - catch_and_ignore_import_warning, -) -from eth.abc import ( - AtomicWriteBatchAPI, - DatabaseAPI, -) -from eth.db.diff import ( - DBDiffTracker, - DiffMissingError, -) - -from .base import ( - BaseAtomicDB, - BaseDB, -) - -if TYPE_CHECKING: - with catch_and_ignore_import_warning(): - import plyvel # noqa: F401 - - -class LevelDB(BaseAtomicDB): - logger = logging.getLogger("eth.db.backends.LevelDB") - - # Creates db as a class variable to avoid level db lock error - def __init__(self, db_path: Path = None, max_open_files: int = None) -> None: - if not db_path: - raise TypeError("Please specifiy a valid path for your database.") - try: - with catch_and_ignore_import_warning(): - import plyvel # noqa: F811 - except ImportError: - raise ImportError( - "LevelDB requires the plyvel library which is not available for import." - ) - self.db_path = db_path - self.db = plyvel.DB( - str(db_path), - create_if_missing=True, - error_if_exists=False, - max_open_files=max_open_files, - ) - - def __getitem__(self, key: bytes) -> bytes: - v = self.db.get(key) - if v is None: - raise KeyError(key) - return v - - def __setitem__(self, key: bytes, value: bytes) -> None: - self.db.put(key, value) - - def _exists(self, key: bytes) -> bool: - return self.db.get(key) is not None - - def __delitem__(self, key: bytes) -> None: - if self.db.get(key) is None: - raise KeyError(key) - self.db.delete(key) - - @contextmanager - def atomic_batch(self) -> Iterator[AtomicWriteBatchAPI]: - with self.db.write_batch(transaction=True) as atomic_batch: - readable_batch = LevelDBWriteBatch(self, atomic_batch) - try: - yield readable_batch - finally: - readable_batch.decommission() - - -class LevelDBWriteBatch(BaseDB, AtomicWriteBatchAPI): - """ - A native leveldb write batch does not permit reads on the in-progress data. - This class fills that gap, by tracking the in-progress diff, and adding - a read interface. - """ - - logger = logging.getLogger("eth.db.backends.LevelDBWriteBatch") - - def __init__( - self, original_read_db: DatabaseAPI, write_batch: "plyvel.WriteBatch" - ) -> None: - self._original_read_db = original_read_db - self._write_batch = write_batch - # keep track of the temporary changes made - self._track_diff = DBDiffTracker() - - def __getitem__(self, key: bytes) -> bytes: - if self._track_diff is None: - raise ValidationError("Cannot get data from a write batch, out of context") - - try: - changed_value = self._track_diff[key] - except DiffMissingError as missing: - if missing.is_deleted: - raise KeyError(key) - else: - return self._original_read_db[key] - else: - return changed_value - - def __setitem__(self, key: bytes, value: bytes) -> None: - if self._track_diff is None: - raise ValidationError("Cannot set data from a write batch, out of context") - - self._write_batch.put(key, value) - self._track_diff[key] = value - - def _exists(self, key: bytes) -> bool: - if self._track_diff is None: - raise ValidationError( - "Cannot test data existance from a write batch, out of context" - ) - - try: - self._track_diff[key] - except DiffMissingError as missing: - if missing.is_deleted: - return False - else: - return key in self._original_read_db - else: - return True - - def __delitem__(self, key: bytes) -> None: - if self._track_diff is None: - raise ValidationError( - "Cannot delete data from a write batch, out of context" - ) - - self._write_batch.delete(key) - del self._track_diff[key] - - def decommission(self) -> None: - """ - Prevent any further actions to be taken on this write batch, - called after leaving context - """ - self._track_diff = None diff --git a/mypy.ini b/mypy.ini index 8609d90fed..12decefb24 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,6 +1,8 @@ [mypy] -warn_unused_ignores = True +; TODO: after dropping py39, try enabling this again: +warn_unused_ignores = False + warn_unused_configs = True warn_redundant_casts = True ; TODO: Drop ignore-missing-imports after adding type annotations for eth_utils, coincurve & cytoolz diff --git a/newsfragments/2088.feature.rst b/newsfragments/2088.feature.rst new file mode 100644 index 0000000000..eeeca941fb --- /dev/null +++ b/newsfragments/2088.feature.rst @@ -0,0 +1 @@ +Python 3.10 and 3.11 support. diff --git a/scripts/benchmark/_utils/chain_plumbing.py b/scripts/benchmark/_utils/chain_plumbing.py index 6823771e34..6ea4c48553 100644 --- a/scripts/benchmark/_utils/chain_plumbing.py +++ b/scripts/benchmark/_utils/chain_plumbing.py @@ -1,13 +1,8 @@ -from pathlib import ( - Path, -) -import tempfile from typing import ( Any, Dict, Iterable, Tuple, - Type, ) from eth_keys import ( @@ -24,24 +19,9 @@ from eth import ( constants, ) -from eth.abc import ( - VirtualMachineAPI, -) -from eth.chains.base import ( - MiningChain, -) from eth.chains.mainnet import ( BaseMainnetChain, ) -from eth.db.backends.level import ( - LevelDB, -) -from eth.tools.builder.chain import ( - build, - disable_pow_check, - fork_at, - genesis, -) ALL_VM = [vm for _, vm in BaseMainnetChain.vm_configuration] @@ -87,24 +67,3 @@ ] GenesisState = Iterable[Tuple[Address, Dict[str, Any]]] - - -def get_chain( - vm: Type[VirtualMachineAPI], genesis_state: GenesisState -) -> Iterable[MiningChain]: - with tempfile.TemporaryDirectory() as temp_dir: - level_db_obj = LevelDB(Path(temp_dir)) - level_db_chain = build( - MiningChain, - fork_at(vm, constants.GENESIS_BLOCK_NUMBER), - disable_pow_check(), - genesis(db=level_db_obj, params=GENESIS_PARAMS, state=genesis_state), - ) - yield level_db_chain - - -def get_all_chains( - genesis_state: GenesisState = DEFAULT_GENESIS_STATE, -) -> Iterable[MiningChain]: - for vm in ALL_VM: - yield from get_chain(vm, genesis_state) diff --git a/setup.py b/setup.py index a38f2f410c..60e38111ee 100644 --- a/setup.py +++ b/setup.py @@ -24,9 +24,8 @@ # Installing these libraries may make the evm perform better than # using the default fallbacks though. "eth-extra": [ - "blake2b-py>=0.1.4,<0.2", - "coincurve>=13.0.0,<14.0.0", - "plyvel>=1.2.0,<2", + "blake2b-py>=0.2.0,<0.3.0", + "coincurve>=18.0.0", ], "test": [ "factory-boy==2.11.1", @@ -35,9 +34,9 @@ "pytest>=6.2.4,<7", "pytest-asyncio>=0.10.0,<0.11", "pytest-cov==2.5.1", - "pytest-timeout>=1.4.2,<2", + "pytest-timeout>=2.0.0,<3", "pytest-watch>=4.1.0,<5", - "pytest-xdist==2.3.0", + "pytest-xdist>=3.0", "importlib-metadata<5.0;python_version<'3.8'", ], "lint": [ @@ -118,5 +117,7 @@ "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", ], ) diff --git a/tests/database/test_atomic_database_api.py b/tests/database/test_atomic_database_api.py deleted file mode 100644 index 0032e88ed0..0000000000 --- a/tests/database/test_atomic_database_api.py +++ /dev/null @@ -1,37 +0,0 @@ -import pytest - -from eth.db.atomic import ( - AtomicDB, -) -from eth.db.backends.level import ( - LevelDB, -) -from eth.tools.db.atomic import ( - AtomicDatabaseBatchAPITestSuite, -) -from eth.tools.db.base import ( - DatabaseAPITestSuite, -) - - -@pytest.fixture(params=["atomic", "level"]) -def atomic_db(request, tmpdir): - if request.param == "atomic": - return AtomicDB() - elif request.param == "level": - return LevelDB(db_path=tmpdir.mkdir("level_db_path")) - else: - raise ValueError(f"Unexpected database type: {request.param}") - - -@pytest.fixture -def db(atomic_db): - return atomic_db - - -class TestAtomicDatabaseBatchAPI(AtomicDatabaseBatchAPITestSuite): - pass - - -class TestAtomicDatabaseAPI(DatabaseAPITestSuite): - pass diff --git a/tox.ini b/tox.ini index 98bb11a261..7609044644 100644 --- a/tox.ini +++ b/tox.ini @@ -1,12 +1,12 @@ [tox] envlist= - py{37,38,39}-{core,database,difficulty,transactions,vm} - py39-native-blockchain-{ \ + py{37,38,39,310,311}-{core,database,difficulty,transactions,vm} + py311-native-blockchain-{ \ metropolis, transition, frontier, homestead, tangerine_whistle, \ spurious_dragon, byzantium, constantinople, petersburg, istanbul, \ berlin, london, merge, shanghai \ } - py{38,39}-lint + py{38,39,310,311}-lint docs [isort] @@ -56,6 +56,8 @@ basepython = py37: python3.7 py38: python3.8 py39: python3.9 + py310: python3.10 + py311: python3.11 extras= docs eth-extra @@ -77,6 +79,6 @@ basepython: python extras: {[common-lint]extras} commands: {[common-lint]commands} -[testenv:py{38,39}-lint] +[testenv:py{38,39,310,311}-lint] extras: {[common-lint]extras} commands: {[common-lint]commands}