diff --git a/ipfs_stac/client.py b/ipfs_stac/client.py index bb13fd8..0d51f70 100644 --- a/ipfs_stac/client.py +++ b/ipfs_stac/client.py @@ -17,16 +17,35 @@ import rasterio from yaspin import yaspin + +# Global Variables +ENV_VAR_NAME = "IPFS_GATEWAY" +REMOTE_GATEWAYS = [ + "https://ipfs.io", + "https://cloudflare-ipfs.com", + "https://dweb.link", +] + + def ensure_data_fetched(func): def wrapper(self, *args, **kwargs): if self.data is None: print("Data for asset has not been fetched yet. Fetching now...") self.fetch() return func(self, *args, **kwargs) + return wrapper + class Web3: - def __init__(self, local_gateway=None, api_port=5001, stac_endpoint=None, remote_gateways=None) -> None: + def __init__( + self, + local_gateway='127.0.0.1', + api_port=5001, + gateway_port=8080, + stac_endpoint=None, + remote_gateways=None, + ) -> None: """ web3 client constructor @@ -38,14 +57,34 @@ def __init__(self, local_gateway=None, api_port=5001, stac_endpoint=None, remote if api_port is None: raise ValueError("api_port must be set") + + if gateway_port is None: + raise ValueError("gateway_port must be set") + self.api_port = api_port + self.gateway_port = gateway_port if self.local_gateway: self.startDaemon() - # Remote_gateways is of type List[str] - if remote_gateways: - os.environ["IPFSSPEC_GATEWAYS"] = f'IPFSSPEC_GATEWAYS="http://{self.local_gateway}:{self.api_port},https://ipfs.io,https://gateway.pinata.cloud,https://cloudflare-ipfs.com,https://dweb.link",{remote_gateways.join(",")}' + # Check if the remote gateway env variable already exists + if ENV_VAR_NAME in os.environ: + os.environ[ENV_VAR_NAME] += ( + os.pathsep + f"http://{self.local_gateway}:{self.gateway_port}" + ) + else: + os.environ[ENV_VAR_NAME] = ( + f"http://{self.local_gateway}:{self.gateway_port}" + ) + + # # Add default remote gateways + # for gateway in REMOTE_GATEWAYS: + # os.environ[ENV_VAR_NAME] = os.environ[ENV_VAR_NAME] + os.pathsep + gateway + + # # Extend additional remote gateways to the environment variable + # if remote_gateways: + # os.environ[ENV_VAR_NAME] += os.pathsep + remote_gateways + def forceLocalNode(self) -> None: """ @@ -53,26 +92,29 @@ def forceLocalNode(self) -> None: This function needs to be refactored slightly -> currently overwrites .env file which is unideal if user has other variables configured """ if self.local_gateway is None: - os.environ["IPFSSPEC_GATEWAYS"] = f'IPFSSPEC_GATEWAYS="http://{self.local_gateway}:{self.api_port},https://ipfs.io,https://gateway.pinata.cloud,https://cloudflare-ipfs.com,https://dweb.link"' + os.environ["ENV_VAR_NAME"] = ( + f'ENV_VAR_NAME="http://{self.local_gateway}:{self.api_port},https://ipfs.io,https://gateway.pinata.cloud,https://cloudflare-ipfs.com,https://dweb.link"' + ) else: - os.environ["IPFSSPEC_GATEWAYS"] = f'IPFSSPEC_GATEWAYS="{self.local_gateway}"' + os.environ["IPFSSPEC_GATEWAYS"] = ( + f'IPFSSPEC_GATEWAYS="{self.local_gateway}"' + ) - def startDaemon(self) -> None: + def startDaemon(self) -> None: """ Starts Kubo CLI Daemon if not already running """ + _process = subprocess.Popen(["ipfs", "daemon"]) try: - requests.get(f"http://{self.local_gateway}:{self.api_port}/") + heartbeat_response = requests.post( + f"http://{self.local_gateway}:{self.api_port}/api/v0/id" + ) + if heartbeat_response.status_code != 200: + warnings.warn( + "IPFS Daemon is running but still can't connect. Check your IPFS configuration." + ) except requests.exceptions.ConnectionError: - warnings.warn("IPFS Daemon is not running... Attempting to launch") - subprocess.Popen(["ipfs", "daemon"]) - - time.sleep(5) - - try: - requests.get(f"http://{self.local_gateway}:{self.api_port}/") - except requests.exceptions.ConnectionError: - raise Exception("Failed to start IPFS daemon") + raise Exception("Failed to start IPFS daemon") def getFromCID(self, cid: str) -> bytes: """ diff --git a/requirements.txt b/requirements.txt index 21258ba..0e28df3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,12 +16,12 @@ docutils==0.20.1 exceptiongroup==1.1.2 fonttools==4.40.0 frozenlist==1.3.3 -fsspec==2023.6.0 +fsspec==2024.9.0 idna==3.4 importlib-metadata==6.7.0 importlib-resources==5.13.0 iniconfig==2.0.0 -ipfsspec==0.4.0 +ipfsspec==0.5.2 jaraco.classes==3.2.3 jsonschema==4.18.0 jsonschema-specifications==2023.6.1 diff --git a/tests/test_client.py b/tests/test_client.py index 38a184c..2484df8 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -17,6 +17,7 @@ LOCAL_GATEWAY = "127.0.0.1" API_PORT = 5001 STAC_ENDPOINT = "fake_endpoint" +GATEWAY_PORT = 8081 @patch('requests.get') @@ -50,7 +51,7 @@ def test_to_pd_df(mock_getFromCID, mock_get): class TestWeb3(SetUp): def setUp(self): - self.client = Web3(local_gateway=LOCAL_GATEWAY, stac_endpoint=STAC_ENDPOINT) + self.client = Web3(local_gateway=LOCAL_GATEWAY, stac_endpoint=STAC_ENDPOINT, gateway_port=GATEWAY_PORT) def test_init(self): self.assertEqual(self.client.local_gateway, LOCAL_GATEWAY) diff --git a/tests/test_client_integration.py b/tests/test_client_integration.py index a91623d..87b4f18 100644 --- a/tests/test_client_integration.py +++ b/tests/test_client_integration.py @@ -12,10 +12,11 @@ LOCAL_GATEWAY = "127.0.0.1" API_PORT = 5001 STAC_ENDPOINT = "http://ec2-54-172-212-55.compute-1.amazonaws.com/api/v1/pgstac/" +GATEWAY_PORT = 8081 class TestIntegration(SetUp): def setUp(self): - self.client = Web3(local_gateway=LOCAL_GATEWAY, stac_endpoint=STAC_ENDPOINT) + self.client = Web3(local_gateway=LOCAL_GATEWAY, stac_endpoint=STAC_ENDPOINT, gateway_port=GATEWAY_PORT) # Colosseum, Rome, Italy self.bbox = [12.490827, 41.889249, 12.494162, 41.891876]