From a1cddb3e34b2d57228e1f4a62fc1bea39cbbf4af Mon Sep 17 00:00:00 2001 From: Patrick Collins <54278053+PatrickAlphaC@users.noreply.github.com> Date: Fri, 22 Nov 2024 15:40:40 -0500 Subject: [PATCH] feat: add filename to deployments db (#345) add filename to deployments db and the appropriate migration --- CONTRIBUTING.md | 6 ++++ boa/deployments.py | 15 +++++++- boa/network.py | 2 ++ .../network/anvil/test_network_env.py | 35 +++++++++++++++++-- 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b2dba295..c292085f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -72,6 +72,12 @@ git commit -m 'your commit message' git push ``` +4. Run the linter + +```bash +make lint +``` + ## Running Tests Once you have your environment setup, you can run the tests to make sure everything is working as expected. You'll need to have your virtual environment activated to run the tests. diff --git a/boa/deployments.py b/boa/deployments.py index 03a3e2af..0b733e62 100644 --- a/boa/deployments.py +++ b/boa/deployments.py @@ -32,6 +32,7 @@ def get_session_id(): class Deployment: contract_address: Address # receipt_dict["createAddress"] contract_name: str + filename: str rpc: str deployer: Address # ostensibly equal to tx_dict["from"] tx_hash: str @@ -90,6 +91,7 @@ def from_sql_tuple(cls, values): session_id text, contract_address text, contract_name text, + filename text, rpc text, deployer text, tx_hash text, @@ -110,9 +112,12 @@ def __init__(self, path=":memory:"): # once 3.12 is min version, use autocommit=True self.db = sqlite3.connect(path) - self.db.execute(_CREATE_CMD) + # Migration for legacy DB without filename column + # We can/should remove this after some time (all 4 users migrate) + self._apply_filename_migration() + def __del__(self): self.db.close() @@ -127,6 +132,14 @@ def insert_deployment(self, deployment: Deployment): self.db.execute(insert_cmd, tuple(values.values())) self.db.commit() + def _apply_filename_migration(self) -> None: + cursor = self.db.execute("PRAGMA table_info(deployments);") + columns = [col[1] for col in cursor.fetchall()] + is_in_db = "filename" in columns + if is_in_db: + return + self.db.execute("ALTER TABLE deployments ADD COLUMN filename text;") + def _get_deployments_from_sql(self, sql_query: str, parameters=(), /): cur = self.db.execute(sql_query, parameters) return (Deployment.from_sql_tuple(item) for item in cur) diff --git a/boa/network.py b/boa/network.py index 23dd0dd1..856bcd58 100644 --- a/boa/network.py +++ b/boa/network.py @@ -403,6 +403,7 @@ def deploy( if (deployments_db := get_deployments_db()) is not None: contract_name = getattr(contract, "contract_name", None) + filename = getattr(contract, "filename", None) try: source_bundle = get_verification_bundle(contract) except Exception as e: @@ -419,6 +420,7 @@ def deploy( deployment_data = Deployment( create_address, contract_name, + filename, self._rpc.name, sender, receipt["transactionHash"], diff --git a/tests/integration/network/anvil/test_network_env.py b/tests/integration/network/anvil/test_network_env.py index 6a289523..f0f816f1 100644 --- a/tests/integration/network/anvil/test_network_env.py +++ b/tests/integration/network/anvil/test_network_env.py @@ -1,9 +1,13 @@ +import sqlite3 +import tempfile +from pathlib import Path + import pytest from hypothesis import given, settings import boa import boa.test.strategies as vy -from boa.deployments import DeploymentsDB, set_deployments_db +from boa.deployments import _CREATE_CMD, DeploymentsDB, set_deployments_db from boa.network import NetworkEnv from boa.rpc import to_bytes from boa.util.abi import Address @@ -77,9 +81,10 @@ def test_deployment_db_overriden_contract_name(): with set_deployments_db(DeploymentsDB(":memory:")) as db: arg = 5 contract_name = "test_deployment" + filename = "my_filename" # contract is written to deployments db - contract = boa.loads(code, arg, name=contract_name) + contract = boa.loads(code, arg, name=contract_name, filename=filename) # test get_deployments() deployment = next(db.get_deployments()) @@ -89,6 +94,7 @@ def test_deployment_db_overriden_contract_name(): # sanity check all the fields assert deployment.contract_address == contract.address assert deployment.contract_name == contract.contract_name + assert deployment.filename == contract.filename assert deployment.contract_name == contract_name assert deployment.deployer == boa.env.eoa assert deployment.rpc == boa.env._rpc.name @@ -117,6 +123,7 @@ def test_deployment_db_no_overriden_name(): # sanity check all the fields assert deployment.contract_address == contract.address assert deployment.contract_name == contract.contract_name + assert deployment.filename == "" assert deployment.contract_name != non_contract_name assert deployment.deployer == boa.env.eoa assert deployment.rpc == boa.env._rpc.name @@ -127,3 +134,27 @@ def test_deployment_db_no_overriden_name(): assert to_bytes(deployment.tx_dict["data"]) == initcode assert deployment.tx_dict["chainId"] == hex(boa.env.get_chain_id()) assert Address(deployment.receipt_dict["contractAddress"]) == contract.address + + +@pytest.fixture +def temp_legacy_db_path() -> Path: + temp_dir = Path(tempfile.mkdtemp()) + db_path = temp_dir / "test.db" + conn = sqlite3.connect(db_path) + conn.execute(_CREATE_CMD) + DROP_COLUMN_SQL = "ALTER TABLE deployments DROP COLUMN filename;" + conn.execute(DROP_COLUMN_SQL) + return db_path + + +def test_deployments_db_migration(temp_legacy_db_path): + sql_db = sqlite3.connect(temp_legacy_db_path) + cursor = sql_db.execute("PRAGMA table_info(deployments);") + columns = [col[1] for col in cursor.fetchall()] + assert "filename" not in columns + + # This next line is what does the migration (added the filename column) + db = DeploymentsDB(temp_legacy_db_path) + cursor = db.db.execute("PRAGMA table_info(deployments);") + columns = [col[1] for col in cursor.fetchall()] + assert "filename" in columns