Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AsyncIPNSFileSystem #32

Merged
merged 2 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ipfsspec/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .async_ipfs import AsyncIPFSFileSystem
from .async_ipfs import AsyncIPFSFileSystem, AsyncIPNSFileSystem

from ._version import get_versions
__version__ = get_versions()['version']
del get_versions

__all__ = ["__version__", "AsyncIPFSFileSystem"]
__all__ = ["__version__", "AsyncIPFSFileSystem", "AsyncIPNSFileSystem"]
31 changes: 18 additions & 13 deletions ipfsspec/async_ipfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,9 @@ def _raise_not_found_for_status(self, response, url):
class AsyncIPFSGateway(AsyncIPFSGatewayBase):
resolution = "path"

def __init__(self, url):
def __init__(self, url, protocol="ipfs"):
self.url = url
self.protocol = protocol

async def api_get(self, endpoint, session, **kwargs):
res = await session.get(self.url + "/api/v0/" + endpoint, params=kwargs, trace_request_ctx={'gateway': self.url})
Expand All @@ -106,7 +107,7 @@ async def api_post(self, endpoint, session, **kwargs):
async def _cid_req(self, method, path, headers=None, **kwargs):
headers = headers or {}
if self.resolution == "path":
res = await method(self.url + "/ipfs/" + path, trace_request_ctx={'gateway': self.url}, headers=headers, **kwargs)
res = await method("/".join((self.url, self.protocol, path)), trace_request_ctx={'gateway': self.url}, headers=headers, **kwargs)
elif self.resolution == "subdomain":
raise NotImplementedError("subdomain resolution is not yet implemented")
else:
Expand Down Expand Up @@ -145,17 +146,17 @@ async def get_client(**kwargs):
return aiohttp.ClientSession(**kwargs)


def gateway_from_file(gateway_path):
def gateway_from_file(gateway_path, protocol="ipfs"):
if gateway_path.exists():
with open(gateway_path) as gw_file:
ipfs_gateway = gw_file.readline().strip()
logger.debug("using IPFS gateway from %s: %s", gateway_path, ipfs_gateway)
return AsyncIPFSGateway(ipfs_gateway)
return AsyncIPFSGateway(ipfs_gateway, protocol=protocol)
return None


@lru_cache
def get_gateway():
def get_gateway(protocol="ipfs"):
"""
Get IPFS gateway according to IPIP-280

Expand All @@ -166,29 +167,29 @@ def get_gateway():
ipfs_gateway = os.environ.get("IPFS_GATEWAY", "")
if ipfs_gateway:
logger.debug("using IPFS gateway from IPFS_GATEWAY environment variable: %s", ipfs_gateway)
return AsyncIPFSGateway(ipfs_gateway)
return AsyncGateway(ipfs_gateway, protocol)

# internal configuration: accept IPFSSPEC_GATEWAYS for backwards compatibility
if ipfsspec_gateways := os.environ.get("IPFSSPEC_GATEWAYS", ""):
ipfs_gateway = ipfsspec_gateways.split()[0]
logger.debug("using IPFS gateway from IPFSSPEC_GATEWAYS environment variable: %s", ipfs_gateway)
warnings.warn("The IPFSSPEC_GATEWAYS environment variable is deprecated, please configure your IPFS Gateway according to IPIP-280, e.g. by using the IPFS_GATEWAY environment variable or using the ~/.ipfs/gateway file.", DeprecationWarning)
return AsyncIPFSGateway(ipfs_gateway)
return AsyncGateway(ipfs_gateway, protocol)

# check various well-known files for possible gateway configurations
if ipfs_path := os.environ.get("IPFS_PATH", ""):
if ipfs_gateway := gateway_from_file(Path(ipfs_path) / "gateway"):
if ipfs_gateway := gateway_from_file(Path(ipfs_path) / "gateway", protocol):
return ipfs_gateway

if home := os.environ.get("HOME", ""):
if ipfs_gateway := gateway_from_file(Path(home) / ".ipfs" / "gateway"):
if ipfs_gateway := gateway_from_file(Path(home) / ".ipfs" / "gateway", protocol):
return ipfs_gateway

if config_home := os.environ.get("XDG_CONFIG_HOME", ""):
if ipfs_gateway := gateway_from_file(Path(config_home) / "ipfs" / "gateway"):
if ipfs_gateway := gateway_from_file(Path(config_home) / "ipfs" / "gateway", protocol):
return ipfs_gateway

if ipfs_gateway := gateway_from_file(Path("/etc") / "ipfs" / "gateway"):
if ipfs_gateway := gateway_from_file(Path("/etc") / "ipfs" / "gateway", protocol):
return ipfs_gateway

system = platform.system()
Expand All @@ -213,7 +214,7 @@ def get_gateway():
candidates = []

for candidate in candidates:
if ipfs_gateway := gateway_from_file(candidate):
if ipfs_gateway := gateway_from_file(candidate, protocol):
return ipfs_gateway

# if we reach this point, no gateway is configured
Expand Down Expand Up @@ -249,7 +250,7 @@ def __init__(self, asynchronous=False, loop=None, client_kwargs=None, **storage_

@property
def gateway(self):
return get_gateway()
return get_gateway(self.protocol)

@staticmethod
def close_session(loop, session):
Expand Down Expand Up @@ -300,3 +301,7 @@ def open(self, path, mode="rb", block_size=None, cache_options=None, **kwargs):
def ukey(self, path):
"""returns the CID, which is by definition an unchanging identitifer"""
return self.info(path)["CID"]


class AsyncIPNSFileSystem(AsyncIPFSFileSystem):
protocol = "ipns"
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
entry_points={
'fsspec.specs': [
'ipfs=ipfsspec.AsyncIPFSFileSystem',
'ipns=ipfsspec.AsyncIPNSFileSystem',
],
},
)
Loading