Repository: ethereum/eth-tester (language: python)

Issue:
feat: Python 3.12 support
Hello team,

This part of the code is failing on Python 3.12:

https://github.com/ethereum/eth-tester/blob/3c76d34beb3ade64ec4569462b36351bdb9a0821/eth_tester/backends/pyevm/utils.py#L5

Do you plan to work on Python 3.12 support (maybe are you already working on it? 🤞🏻 😈)?


Discussion / hints:

Fix patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 48aef689..9bf4f8d8 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -25,9 +25,6 @@ common: &common
         command: |
           python -m pip install --upgrade pip
           python -m pip install tox
-    - run:
-        name: install pre-commit
-        command: python -m pip install --progress-bar=off pre-commit
     - run:
         name: run tox
         command: python -m tox run -r
@@ -42,34 +39,67 @@ common: &common
 orbs:
   win: circleci/windows@5.0.0
 
-windows_steps: &windows_steps
-  executor:
-    name: win/default
-    shell: bash.exe
-  working_directory: C:\Users\circleci\project\eth-tester
+windows-wheel-steps:
+  windows-wheel-setup: &windows-wheel-setup
+    executor:
+      name: win/default
+      shell: bash.exe
+    working_directory: C:\Users\circleci\project\eth-tester
+    environment:
+      TOXENV: windows-wheel
+  restore-cache-step: &restore-cache-step
+    restore_cache:
+      keys:
+        - cache-v1-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "setup.py" }}-{{ checksum "tox.ini" }}
+  install-pyenv-step: &install-pyenv-step
+    run:
+      name: install pyenv
+      command: |
+        pip install pyenv-win --target $HOME/.pyenv
+        echo 'export PYENV="$HOME/.pyenv/pyenv-win/"' >> $BASH_ENV
+        echo 'export PYENV_ROOT="$HOME/.pyenv/pyenv-win/"' >> $BASH_ENV
+        echo 'export PYENV_USERPROFILE="$HOME/.pyenv/pyenv-win/"' >> $BASH_ENV
+        echo 'export PATH="$PATH:$HOME/.pyenv/pyenv-win/bin"' >> $BASH_ENV
+        echo 'export PATH="$PATH:$HOME/.pyenv/pyenv-win/shims"' >> $BASH_ENV
+        source $BASH_ENV
+        pyenv update
+  install-latest-python-step: &install-latest-python-step
+    run:
+      name: install latest python version and tox
+      command: |
+        LATEST_VERSION=$(pyenv install --list | grep -E "${MINOR_VERSION}\.[0-9]+$" | tail -1)
+        echo "installing python version $LATEST_VERSION"
+        pyenv install $LATEST_VERSION
+        pyenv global $LATEST_VERSION
+        python3 -m pip install --upgrade pip
+        python3 -m pip install tox
+  run-tox-step: &run-tox-step
+    run:
+      name: run tox
+      command: |
+        echo 'running tox with' $(python3 --version)
+        python3 -m tox run -r
+  save-cache-step: &save-cache-step
+    save_cache:
+      paths:
+        - .tox
+      key: cache-v1-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "setup.py" }}-{{ checksum "tox.ini" }}
+
+docs: &docs
+  docker:
+    - image: common
   steps:
-    - checkout
-    - restore_cache:
-        keys:
-          - cache-v1-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "setup.py" }}-{{ checksum "tox.ini" }}
     - run:
-        name: install dependencies
+        name: install latexpdf dependencies
         command: |
-          python -m pip install --upgrade pip
-          python -m pip install tox
-    - run:
-        name: run tox
-        command: python -m tox run -r
-    - save_cache:
-        paths:
-          - .tox
-        key: cache-v1-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "setup.py" }}-{{ checksum "tox.ini" }}
+          sudo apt-get update
+          sudo apt-get install latexmk tex-gyre texlive-fonts-extra
 
 jobs:
   docs:
-    <<: *common
+    <<: *docs
     docker:
-      - image: cimg/python:3.8
+      - image: cimg/python:3.9
         environment:
           TOXENV: docs
 
@@ -97,6 +127,12 @@ jobs:
       - image: cimg/python:3.11
         environment:
           TOXENV: py311-core
+  py312-core:
+    <<: *common
+    docker:
+      - image: cimg/python:3.12
+        environment:
+          TOXENV: py312-core
 
   py38-lint:
     <<: *common
@@ -122,6 +158,12 @@ jobs:
       - image: cimg/python:3.11
         environment:
           TOXENV: py311-lint
+  py312-lint:
+    <<: *common
+    docker:
+      - image: cimg/python:3.12
+        environment:
+          TOXENV: py312-lint
 
   py38-wheel:
     <<: *common
@@ -147,11 +189,38 @@ jobs:
       - image: cimg/python:3.11
         environment:
           TOXENV: py311-wheel
+  py312-wheel:
+    <<: *common
+    docker:
+      - image: cimg/python:3.12
+        environment:
+          TOXENV: py312-wheel
 
-  py311-wheel-windows:
-    <<: *windows_steps
-    environment:
-      TOXENV: py311-wheel-windows
+  py311-windows-wheel:
+    <<: *windows-wheel-setup
+    steps:
+      - checkout
+      - <<: *restore-cache-step
+      - <<: *install-pyenv-step
+      - run:
+          name: set minor version
+          command: echo "export MINOR_VERSION='3.11'" >> $BASH_ENV
+      - <<: *install-latest-python-step
+      - <<: *run-tox-step
+      - <<: *save-cache-step
+
+  py312-windows-wheel:
+    <<: *windows-wheel-setup
+    steps:
+      - checkout
+      - <<: *restore-cache-step
+      - <<: *install-pyenv-step
+      - run:
+          name: set minor version
+          command: echo "export MINOR_VERSION='3.12'" >> $BASH_ENV
+      - <<: *install-latest-python-step
+      - <<: *run-tox-step
+      - <<: *save-cache-step
 
   py38-pyevm:
     <<: *common
@@ -177,26 +246,49 @@ jobs:
       - image: cimg/python:3.11
         environment:
           TOXENV: py311-pyevm
+  py312-pyevm:
+    <<: *common
+    docker:
+      - image: cimg/python:3.12
+        environment:
+          TOXENV: py312-pyevm
+
+define: &all_jobs
+  - docs
+  - py38-core
+  - py39-core
+  - py310-core
+  - py311-core
+  - py312-core
+  - py38-lint
+  - py39-lint
+  - py310-lint
+  - py311-lint
+  - py312-lint
+  - py38-wheel
+  - py39-wheel
+  - py310-wheel
+  - py311-wheel
+  - py312-wheel
+  - py311-windows-wheel
+  - py312-windows-wheel
+  - py38-pyevm
+  - py39-pyevm
+  - py310-pyevm
+  - py311-pyevm
+  - py312-pyevm
 
 workflows:
   version: 2
   test:
-    jobs:
-      - docs
-      - py38-core
-      - py39-core
-      - py310-core
-      - py311-core
-      - py38-lint
-      - py39-lint
-      - py310-lint
-      - py311-lint
-      - py38-wheel
-      - py39-wheel
-      - py310-wheel
-      - py311-wheel
-      - py311-wheel-windows
-      - py38-pyevm
-      - py39-pyevm
-      - py310-pyevm
-      - py311-pyevm
+    jobs: *all_jobs
+  nightly:
+    triggers:
+      - schedule:
+          # Weekdays 12:00p UTC
+          cron: "0 12 * * 1,2,3,4,5"
+          filters:
+            branches:
+              only:
+                - main
+    jobs: *all_jobs
diff --git a/.gitignore b/.gitignore
index 5127a4df..57eac529 100644
--- a/.gitignore
+++ b/.gitignore
@@ -60,6 +60,9 @@ chains
 .cache
 .pytest_cache
 
+# pycache
+__pycache__/
+
 # Test output logs
 logs
 
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index e5a30f26..84b40c0d 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -7,6 +7,11 @@ repos:
     -   id: check-toml
     -   id: end-of-file-fixer
     -   id: trailing-whitespace
+-   repo: https://github.com/asottile/pyupgrade
+    rev: v3.15.0
+    hooks:
+    -   id: pyupgrade
+        args: [--py38-plus]
 -   repo: https://github.com/psf/black
     rev: 23.9.1
     hooks:
@@ -43,3 +48,8 @@ repos:
     hooks:
     -   id: mypy
         exclude: 'tests/|eth_tester/'
+-   repo: https://github.com/PrincetonUniversity/blocklint
+    rev: v0.2.5
+    hooks:
+    -   id: blocklint
+        exclude: 'docs/Makefile|docs/release_notes.rst|tox.ini|CHANGELOG.rst|README.md'
diff --git a/MANIFEST.in b/MANIFEST.in
index a122460c..0584923e 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,6 +1,7 @@
 include LICENSE
 include README.md
 
+recursive-include scripts *
 recursive-include tests *
 
 global-include *.pyi
diff --git a/Makefile b/Makefile
index 94072525..9f622392 100644
--- a/Makefile
+++ b/Makefile
@@ -31,7 +31,7 @@ lint:
 	)
 
 test:
-	pytest tests
+	python -m pytest tests
 
 docs:
 	python ./newsfragments/validate_files.py
@@ -49,11 +49,11 @@ notes: check-bump
 	towncrier build --yes --version $(UPCOMING_VERSION)
 	# Before we bump the version, make sure that the towncrier-generated docs will build
 	make docs
-	git commit -m "Compile release notes"
+	git commit -m "Compile release notes for v$(UPCOMING_VERSION)"
 
 release: check-bump clean
 	# require that upstream is configured for ethereum/eth-tester
-	git remote -v | grep "upstream\tgit@github.com:ethereum/eth-tester.git (push)\|upstream\thttps://github.com/ethereum/eth-tester (push)"
+	@git remote -v | grep "upstream[[:space:]]git@github.com:ethereum/eth-tester.git (push)\|upstream[[:space:]]https://github.com/ethereum/eth-tester (push)"
 	# verify that docs build correctly
 	./newsfragments/validate_files.py is-empty
 	make docs
diff --git a/newsfragments/290.internal.rst b/newsfragments/290.internal.rst
new file mode 100644
index 00000000..929b02bf
--- /dev/null
+++ b/newsfragments/290.internal.rst
@@ -0,0 +1,1 @@
+Merge template updates, notably adding python 3.12 support
diff --git a/pyproject.toml b/pyproject.toml
index 66f31f82..f3a5eba7 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,32 +1,34 @@
 [tool.autoflake]
-remove_all_unused_imports = "True"
 exclude = "__init__.py"
+remove_all_unused_imports = true
 
 [tool.isort]
-combine_as_imports = "True"
+combine_as_imports = true
 extra_standard_library = "pytest"
 force_grid_wrap = 1
-force_sort_within_sections = "True"
-known_third_party = "hypothesis,pytest"
+force_sort_within_sections = true
+honor_noqa = true
 known_first_party = "eth_tester"
+known_third_party = "hypothesis"
 multi_line_output = 3
 profile = "black"
+use_parentheses = true
 
 [tool.mypy]
-check_untyped_defs = "True"
-disallow_incomplete_defs = "True"
-disallow_untyped_defs = "True"
-disallow_any_generics = "True"
-disallow_untyped_calls = "True"
-disallow_untyped_decorators = "True"
-disallow_subclassing_any = "True"
-ignore_missing_imports = "True"
-strict_optional = "True"
-strict_equality = "True"
-warn_redundant_casts = "True"
-warn_return_any = "True"
-warn_unused_configs = "True"
-warn_unused_ignores = "True"
+check_untyped_defs = true
+disallow_any_generics = true
+disallow_incomplete_defs = true
+disallow_subclassing_any = true
+disallow_untyped_calls = true
+disallow_untyped_decorators = true
+disallow_untyped_defs = true
+ignore_missing_imports = true
+strict_equality = true
+strict_optional = true
+warn_redundant_casts = true
+warn_return_any = true
+warn_unused_configs = true
+warn_unused_ignores = true
 
 
 [tool.pydocstyle]
@@ -63,18 +65,18 @@ add-ignore = "D200,D203,D204,D205,D212,D302,D400,D401,D412,D415"
 
 [tool.pytest.ini_options]
 addopts = "-v --showlocals --durations 10"
-xfail_strict = "True"
-log_format = "%(levelname)8s  %(asctime)s  %(filename)20s  %(message)s"
 log_date_format = "%m-%d %H:%M:%S"
+log_format = "%(levelname)8s  %(asctime)s  %(filename)20s  %(message)s"
+xfail_strict = true
 
 [tool.towncrier]
 # Read https://github.com/ethereum/eth-tester/blob/main/newsfragments/README.md for instructions
-package = "eth_tester"
-filename = "CHANGELOG.rst"
 directory = "newsfragments"
-underlines = ["-", "~", "^"]
-title_format = "eth-tester v{version} ({project_date})"
+filename = "CHANGELOG.rst"
 issue_format = "`#{issue} <https://github.com/ethereum/eth-tester/issues/{issue}>`__"
+package = "eth_tester"
+title_format = "eth-tester v{version} ({project_date})"
+underlines = ["-", "~", "^"]
 
 [[tool.towncrier.type]]
 directory = "breaking"
diff --git a/setup.py b/setup.py
index 20d57c81..a71f8372 100644
--- a/setup.py
+++ b/setup.py
@@ -1,5 +1,4 @@
 #!/usr/bin/env python
-# -*- coding: utf-8 -*-
 from setuptools import (
     find_packages,
     setup,
@@ -69,7 +68,7 @@
     license="MIT",
     zip_safe=False,
     keywords="ethereum",
-    packages=find_packages(exclude=["tests", "tests.*"]),
+    packages=find_packages(exclude=["scripts", "scripts.*", "tests", "tests.*"]),
     package_data={"eth_tester": ["py.typed"]},
     classifiers=[
         "Development Status :: 2 - Pre-Alpha",
@@ -81,5 +80,6 @@
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",
+        "Programming Language :: Python :: 3.12",
     ],
 )
diff --git a/tox.ini b/tox.ini
index 60816615..d270d241 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,10 +1,10 @@
 [tox]
 envlist=
-    py{38,39,310,311}-core
-    py{38,39,310,311}-lint
-    py{38,39,310,311}-wheel
-    py311-wheel-windows
-    py{38,39,310,311}-pyevm
+    py{38,39,310,311,312}-core
+    py{38,39,310,311,312}-lint
+    py{38,39,310,311,312}-wheel
+    py{38,39,310,311,312}-pyevm
+    windows-wheel
     docs
 
 [flake8]
@@ -13,6 +13,9 @@ extend-ignore=E203
 max-line-length=88
 per-file-ignores=__init__.py:F401
 
+[blocklint]
+max_issue_threshold=1
+
 [testenv]
 usedevelop=True
 commands=
@@ -23,22 +26,25 @@ deps =
     coincurve>=6.0.0
 basepython=
     docs: python
+    windows-wheel: python
     py38: python3.8
     py39: python3.9
     py310: python3.10
     py311: python3.11
+    py312: python3.12
 extras=
     test
     docs
     pyevm: py-evm
 allowlist_externals=make,pre-commit
 
-[testenv:py{38,39,310,311}-lint]
+[testenv:py{38,39,310,311,312}-lint]
 deps=pre-commit
 commands=
+    pre-commit install
     pre-commit run --all-files --show-diff-on-failure
 
-[testenv:py{38,39,310,311}-wheel]
+[testenv:py{38,39,310,311,312}-wheel]
 deps=
     wheel
     build[virtualenv]
@@ -53,13 +59,14 @@ commands=
     python -c "import eth_tester"
 skip_install=true
 
-[testenv:py311-wheel-windows]
+[testenv:windows-wheel]
 deps=
     wheel
     build[virtualenv]
 allowlist_externals=
     bash.exe
 commands=
+    python --version
     python -m pip install --upgrade pip
     bash.exe -c "rm -rf build dist"
     python -m build


Test patch:
diff --git a/eth_tester/backends/mock/factory.py b/eth_tester/backends/mock/factory.py
index 19d9af00..e555b9d6 100644
--- a/eth_tester/backends/mock/factory.py
+++ b/eth_tester/backends/mock/factory.py
@@ -75,9 +75,9 @@ def bytes_repr(value):
     elif is_integer(value):
         yield to_bytes(value)
     elif is_null(value):
-        yield "None@{}".format(id(value))
+        yield f"None@{id(value)}"
     else:
-        raise TypeError("Unsupported type for bytes_repr: {}".format(type(value)))
+        raise TypeError(f"Unsupported type for bytes_repr: {type(value)}")
 
 
 def fake_rlp_hash(value):
diff --git a/eth_tester/backends/pyevm/__init__.py b/eth_tester/backends/pyevm/__init__.py
index 91de31e0..ed07976b 100644
--- a/eth_tester/backends/pyevm/__init__.py
+++ b/eth_tester/backends/pyevm/__init__.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    absolute_import,
-)
-
 from .main import (
     PyEVMBackend,
 )
diff --git a/eth_tester/backends/pyevm/main.py b/eth_tester/backends/pyevm/main.py
index f098b23f..eb81531f 100644
--- a/eth_tester/backends/pyevm/main.py
+++ b/eth_tester/backends/pyevm/main.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    absolute_import,
-)
-
 import os
 import time
 from typing import (
diff --git a/eth_tester/backends/pyevm/utils.py b/eth_tester/backends/pyevm/utils.py
index ce408936..9899855a 100644
--- a/eth_tester/backends/pyevm/utils.py
+++ b/eth_tester/backends/pyevm/utils.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    absolute_import,
-)
-
 from importlib.metadata import (
     PackageNotFoundError,
     version,
diff --git a/eth_tester/constants.py b/eth_tester/constants.py
index 883db641..a09d9655 100644
--- a/eth_tester/constants.py
+++ b/eth_tester/constants.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    unicode_literals,
-)
-
 UINT256_MIN = 0
 UINT256_MAX = 2**256 - 1
 UINT64_MAX = 2**64 - 1
diff --git a/eth_tester/main.py b/eth_tester/main.py
index 2bc02bf9..7828a4a0 100644
--- a/eth_tester/main.py
+++ b/eth_tester/main.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    unicode_literals,
-)
-
 import collections
 import functools
 import itertools
@@ -167,7 +163,7 @@ def _reset_local_state(self):
 
         # raw accounts
         self._account_passwords = {}
-        self._account_unlock = collections.defaultdict(lambda: False)
+        self._account_unlock = collections.defaultdict(bool)
 
     #
     # Time Traveling
diff --git a/eth_tester/normalization/__init__.py b/eth_tester/normalization/__init__.py
index b2582af8..8fcc1da4 100644
--- a/eth_tester/normalization/__init__.py
+++ b/eth_tester/normalization/__init__.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    absolute_import,
-)
-
 import os
 
 from eth_tester.utils.module_loading import (
diff --git a/eth_tester/normalization/inbound.py b/eth_tester/normalization/inbound.py
index bbd049e6..e63bcfad 100644
--- a/eth_tester/normalization/inbound.py
+++ b/eth_tester/normalization/inbound.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    absolute_import,
-)
-
 from eth_utils import (
     to_bytes,
 )
diff --git a/eth_tester/normalization/outbound.py b/eth_tester/normalization/outbound.py
index f9955dfd..96730616 100644
--- a/eth_tester/normalization/outbound.py
+++ b/eth_tester/normalization/outbound.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    absolute_import,
-)
-
 from eth_utils import (
     is_integer,
 )
diff --git a/eth_tester/py.typed b/eth_tester/py.typed
new file mode 100644
index 00000000..e69de29b
diff --git a/eth_tester/tools/gas_burner_contract.py b/eth_tester/tools/gas_burner_contract.py
index 454fc7c4..f9b89cd7 100644
--- a/eth_tester/tools/gas_burner_contract.py
+++ b/eth_tester/tools/gas_burner_contract.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    unicode_literals,
-)
-
 from eth_abi import (
     abi,
 )
diff --git a/eth_tester/utils/backend_testing.py b/eth_tester/utils/backend_testing.py
index 7523627a..fddc4cac 100644
--- a/eth_tester/utils/backend_testing.py
+++ b/eth_tester/utils/backend_testing.py
@@ -1,6 +1,4 @@
-from __future__ import (
-    unicode_literals,
-)
+import pytest
 
 from eth_keys import (
     keys,
@@ -19,7 +17,6 @@
     dissoc,
     merge,
 )
-import pytest
 import rlp
 
 from eth_tester.constants import (
diff --git a/eth_tester/utils/emitter_contract.py b/eth_tester/utils/emitter_contract.py
index 69dd51ba..8c118eec 100644
--- a/eth_tester/utils/emitter_contract.py
+++ b/eth_tester/utils/emitter_contract.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    unicode_literals,
-)
-
 from eth_abi import (
     abi,
 )
diff --git a/eth_tester/utils/encoding.py b/eth_tester/utils/encoding.py
index 81c63deb..248c7532 100644
--- a/eth_tester/utils/encoding.py
+++ b/eth_tester/utils/encoding.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    unicode_literals,
-)
-
 from eth_utils import (
     int_to_big_endian,
 )
diff --git a/eth_tester/utils/math_contract.py b/eth_tester/utils/math_contract.py
index e0084e5d..4e5fa3c0 100644
--- a/eth_tester/utils/math_contract.py
+++ b/eth_tester/utils/math_contract.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    unicode_literals,
-)
-
 from eth_abi import (
     abi,
 )
diff --git a/eth_tester/utils/module_loading.py b/eth_tester/utils/module_loading.py
index 5a3d02bf..4a96ba5d 100644
--- a/eth_tester/utils/module_loading.py
+++ b/eth_tester/utils/module_loading.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    absolute_import,
-)
-
 from importlib import (
     import_module,
 )
diff --git a/eth_tester/utils/throws_contract.py b/eth_tester/utils/throws_contract.py
index e8c1ac8c..692e7a93 100644
--- a/eth_tester/utils/throws_contract.py
+++ b/eth_tester/utils/throws_contract.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    unicode_literals,
-)
-
 from eth_abi import (
     abi,
 )
diff --git a/eth_tester/validation/__init__.py b/eth_tester/validation/__init__.py
index 5cb53094..e7867742 100644
--- a/eth_tester/validation/__init__.py
+++ b/eth_tester/validation/__init__.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    absolute_import,
-)
-
 import os
 
 from eth_tester.utils.module_loading import (
diff --git a/eth_tester/validation/base.py b/eth_tester/validation/base.py
index 92ead5a0..1d822ed2 100644
--- a/eth_tester/validation/base.py
+++ b/eth_tester/validation/base.py
@@ -1,8 +1,3 @@
-from __future__ import (
-    absolute_import,
-)
-
-
 class BaseValidator:
     #
     # Inbound
diff --git a/eth_tester/validation/common.py b/eth_tester/validation/common.py
index 185441ff..7f9946be 100644
--- a/eth_tester/validation/common.py
+++ b/eth_tester/validation/common.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    unicode_literals,
-)
-
 import functools
 import math
 from typing import (
@@ -63,30 +59,22 @@ def validate_uint(max_val, value):
 
 def validate_bytes(value):
     if not is_bytes(value):
-        raise ValidationError(
-            "Value must be a byte string.  Got type: {}".format(type(value))
-        )
+        raise ValidationError(f"Value must be a byte string.  Got type: {type(value)}")
 
 
 def validate_text(value):
     if not is_text(value):
-        raise ValidationError(
-            "Value must be a text string.  Got type: {}".format(type(value))
-        )
+        raise ValidationError(f"Value must be a text string.  Got type: {type(value)}")
 
 
 def validate_is_dict(value):
     if not is_dict(value):
-        raise ValidationError(
-            "Value must be a dictionary.  Got: {}".format(type(value))
-        )
+        raise ValidationError(f"Value must be a dictionary.  Got: {type(value)}")
 
 
 def validate_is_list_like(value):
     if not is_list_like(value):
-        raise ValidationError(
-            "Value must be a sequence type.  Got: {}".format(type(value))
-        )
+        raise ValidationError(f"Value must be a sequence type.  Got: {type(value)}")
 
 
 @to_tuple
@@ -101,9 +89,7 @@ def _accumulate_errors(value, validators):
 def validate_any(value, validators):
     errors = _accumulate_errors(value, validators)
     if len(errors) == len(validators):
-        item_error_messages = tuple(
-            " - [{}]: {}".format(idx, str(err)) for idx, err in errors
-        )
+        item_error_messages = tuple(f" - [{idx}]: {str(err)}" for idx, err in errors)
         error_message = (
             "Value did not pass any of the provided validators:\n"
             "{}".format("\n".join(item_error_messages))
@@ -151,7 +137,7 @@ def validate_dict(value, key_validators):
     key_errors = _accumulate_dict_errors(value, key_validators)
     if key_errors:
         key_messages = tuple(
-            "{}: {}".format(key, str(err)) for key, err in sorted(key_errors.items())
+            f"{key}: {str(err)}" for key, err in sorted(key_errors.items())
         )
         error_message = "The following keys failed to validate\n" "- {}".format(
             "\n - ".join(key_messages)
@@ -174,7 +160,7 @@ def validate_array(value, validator):
     item_errors = _accumulate_array_errors(value, validator)
     if item_errors:
         item_messages = tuple(
-            "[{}]: {}".format(index, str(err)) for index, err in sorted(item_errors)
+            f"[{index}]: {str(err)}" for index, err in sorted(item_errors)
         )
         error_message = "The following items failed to validate\n" "- {}".format(
             "\n - ".join(item_messages)
diff --git a/eth_tester/validation/default.py b/eth_tester/validation/default.py
index 1ab4e0fe..915d121e 100644
--- a/eth_tester/validation/default.py
+++ b/eth_tester/validation/default.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    absolute_import,
-)
-
 from .base import (
     BaseValidator,
 )
diff --git a/eth_tester/validation/inbound.py b/eth_tester/validation/inbound.py
index 1f5483c2..f60925ab 100644
--- a/eth_tester/validation/inbound.py
+++ b/eth_tester/validation/inbound.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    unicode_literals,
-)
-
 import binascii
 from typing import (
     Dict,
@@ -226,9 +222,7 @@ def validate_transaction(value, txn_internal_type):
             "the `txn_internal_type` parameter must be one of send/call/estimate"
         )
     if not is_dict(value):
-        raise ValidationError(
-            "Transaction must be a dictionary. Got: {}".format(type(value))
-        )
+        raise ValidationError(f"Transaction must be a dictionary. Got: {type(value)}")
 
     unknown_keys = tuple(
         sorted(
diff --git a/eth_tester/validation/outbound.py b/eth_tester/validation/outbound.py
index 9b585742..3f47bdef 100644
--- a/eth_tester/validation/outbound.py
+++ b/eth_tester/validation/outbound.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    unicode_literals,
-)
-
 from eth_utils import (
     is_bytes,
     is_canonical_address,
@@ -48,7 +44,7 @@ def validate_32_byte_string(value):
     validate_bytes(value)
     if len(value) != 32:
         raise ValidationError(
-            "Must be of length 32.  Got: {} of length {}".format(value, len(value))
+            f"Must be of length 32.  Got: {value} of length {len(value)}"
         )
 
 
@@ -59,7 +55,7 @@ def validate_nonce(value):
     validate_bytes(value)
     if len(value) != 8:
         raise ValidationError(
-            "Must be of length 8.  Got: {} of length {}".format(value, len(value))
+            f"Must be of length 8.  Got: {value} of length {len(value)}"
         )
 
 
diff --git a/tests/backends/test_pyevm.py b/tests/backends/test_pyevm.py
index a41de09a..897cd37d 100644
--- a/tests/backends/test_pyevm.py
+++ b/tests/backends/test_pyevm.py
@@ -1,6 +1,4 @@
-from __future__ import (
-    unicode_literals,
-)
+import pytest
 
 from eth.constants import (
     POST_MERGE_DIFFICULTY,
@@ -32,7 +30,6 @@
     to_hex,
     to_wei,
 )
-import pytest
 
 from eth_tester import (
     EthereumTester,
diff --git a/tests/core/filter-utils/test_filter_helpers.py b/tests/core/filter-utils/test_filter_helpers.py
index 89bea204..6acc00d7 100644
--- a/tests/core/filter-utils/test_filter_helpers.py
+++ b/tests/core/filter-utils/test_filter_helpers.py
@@ -1,12 +1,9 @@
-from __future__ import (
-    unicode_literals,
-)
+import pytest
 
 from eth_utils import (
     big_endian_to_int,
     is_list_like,
 )
-import pytest
 
 from eth_tester.utils.filters import (
     check_if_address_match,
diff --git a/tests/core/filter-utils/test_filter_object.py b/tests/core/filter-utils/test_filter_object.py
index 785b13c4..81388da8 100644
--- a/tests/core/filter-utils/test_filter_object.py
+++ b/tests/core/filter-utils/test_filter_object.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    unicode_literals,
-)
-
 import pytest
 
 from eth_tester.utils.filters import (
diff --git a/tests/core/test_account_utils.py b/tests/core/test_account_utils.py
index 218fca90..3d39eefb 100644
--- a/tests/core/test_account_utils.py
+++ b/tests/core/test_account_utils.py
@@ -1,7 +1,8 @@
+import pytest
+
 from eth_utils import (
     decode_hex,
 )
-import pytest
 
 from eth_tester.utils.accounts import (
     private_key_to_address,
diff --git a/tests/core/test_import.py b/tests/core/test_import.py
deleted file mode 100644
index d386abcf..00000000
--- a/tests/core/test_import.py
+++ /dev/null
@@ -1,2 +0,0 @@
-def test_import():
-    import eth_tester  # noqa: F401
diff --git a/tests/core/test_import_and_version.py b/tests/core/test_import_and_version.py
new file mode 100644
index 00000000..717c7381
--- /dev/null
+++ b/tests/core/test_import_and_version.py
@@ -0,0 +1,4 @@
+def test_import_and_version():
+    import eth_tester
+
+    assert isinstance(eth_tester.__version__, str)
diff --git a/tests/core/test_mock_backend.py b/tests/core/test_mock_backend.py
index 5d9ce916..0f9d3419 100644
--- a/tests/core/test_mock_backend.py
+++ b/tests/core/test_mock_backend.py
@@ -1,7 +1,3 @@
-from __future__ import (
-    unicode_literals,
-)
-
 import pytest
 
 from eth_tester import (
diff --git a/tests/core/validation/test_inbound_validation.py b/tests/core/validation/test_inbound_validation.py
index 181ec192..9b293e7d 100644
--- a/tests/core/validation/test_inbound_validation.py
+++ b/tests/core/validation/test_inbound_validation.py
@@ -1,13 +1,10 @@
-from __future__ import (
-    unicode_literals,
-)
+import pytest
 
 from eth_utils import (
     decode_hex,
     encode_hex,
     to_dict,
 )
-import pytest
 
 from eth_tester.exceptions import (
     ValidationError,
diff --git a/tests/core/validation/test_outbound_validation.py b/tests/core/validation/test_outbound_validation.py
index e85914f0..ae8bb863 100644
--- a/tests/core/validation/test_outbound_validation.py
+++ b/tests/core/validation/test_outbound_validation.py
@@ -1,11 +1,8 @@
-from __future__ import (
-    unicode_literals,
-)
+import pytest
 
 from eth_utils import (
     encode_hex,
 )
-import pytest
 from toolz import (
     dissoc,
     merge,