1+ """An fsspec filesystem that proxies via pyscriptapps.com."""
2+
13from json import dumps , loads
24import logging
3- import os
45
56from pyscript import sync , ffi
67from fsspec .spec import AbstractFileSystem , AbstractBufferedFile
78import fsspec .utils
89
910logger = logging .getLogger ("pyscript_fsspec_client" )
1011fsspec .utils .setup_logging (logger = logger )
11- default_endpoint = os .getenv ("FSSPEC_PROXY_URL" , "http://127.0.0.1:8000" )
1212
1313
1414class PyscriptFileSystem (AbstractFileSystem ):
15+ """An fsspec filesystem that proxies via pyscriptapps.com."""
16+
1517 protocol = "pyscript"
1618
17- def __init__ (self , base_url = default_endpoint ):
19+ def __init__ (self , base_url ):
1820 super ().__init__ ()
1921 self .base_url = base_url
2022
21- def _split_path (self , path ):
22- key , * relpath = path .split ("/" , 1 )
23- return key , relpath [0 ] if relpath else ""
23+ # `AbstractFileSystem` protocol ############################################
24+
25+ def cat_file (self , path , start = None , end = None , ** kw ):
26+ if start is not None and end is not None :
27+ range = (start , end + 1 )
28+ else :
29+ range = None
30+ return self ._call (f"bytes/{ path } " , binary = True , range = range )
31+
32+ def ls (self , path , detail = True , ** kwargs ):
33+ path = self ._strip_protocol (path )
34+ out = loads (self ._call (f"list/{ path } " ))["contents" ]
35+
36+ if detail :
37+ return out
38+ return sorted (_ ["name" ] for _ in out )
39+
40+ def pipe_file (self , path , value , mode = "overwrite" , ** kwargs ):
41+ self ._call (f"bytes/{ path } " , method = "POST" , data = value )
42+
43+ def rm_file (self , path ):
44+ path = self ._strip_protocol (path )
45+ self ._call (f"delete/{ path } " , method = "DELETE" , binary = True )
46+
47+ def _open (
48+ self ,
49+ path ,
50+ mode = "rb" ,
51+ block_size = None ,
52+ autocommit = True ,
53+ cache_options = None ,
54+ ** kwargs ,
55+ ):
56+ return JFile (
57+ self , path , mode , block_size , autocommit , cache_options , ** kwargs
58+ )
59+
60+ # Internal #################################################################
2461
2562 def _call (self , path , method = "GET" , range = None , binary = False , data = 0 , json = 0 ):
2663 logger .debug ("request: %s %s %s" , path , method , range )
@@ -47,49 +84,16 @@ def _call(self, path, method="GET", range=None, binary=False, data=0, json=0):
4784 out = bytes (out .to_py ())
4885 return out
4986
50- def ls (self , path , detail = True , ** kwargs ):
51- path = self ._strip_protocol (path )
52- key , * path = path .split ("/" , 1 )
53- if key :
54- part = path [0 ] if path else ""
55- out = loads (self ._call (f"{ key } /list/{ part } " ))["contents" ]
56- else :
57- raise ValueError
58-
59- if detail :
60- return out
61- return sorted (_ ["name" ] for _ in out )
62-
63- def rm_file (self , path ):
64- path = self ._strip_protocol (path )
65- key , path = path .split ("/" , 1 )
66- self ._call (f"{ key } /delete/{ path } " , method = "DELETE" , binary = True )
67-
68- def _open (
69- self ,
70- path ,
71- mode = "rb" ,
72- block_size = None ,
73- autocommit = True ,
74- cache_options = None ,
75- ** kwargs ,
76- ):
77- return JFile (self , path , mode , block_size , autocommit , cache_options , ** kwargs )
87+ def _split_path (self , path ):
88+ key , * relpath = path .split ("/" , 1 )
89+ return key , relpath [0 ] if relpath else ""
7890
79- def cat_file (self , path , start = None , end = None , ** kw ):
80- key , relpath = self ._split_path (path )
81- if start is not None and end is not None :
82- range = (start , end + 1 )
83- else :
84- range = None
85- return self ._call (f"{ key } /bytes/{ relpath } " , binary = True , range = range )
8691
87- def pipe_file (self , path , value , mode = "overwrite" , ** kwargs ):
88- key , relpath = self ._split_path (path )
89- self ._call (f"{ key } /bytes/{ relpath } " , method = "POST" , data = value )
92+ class JFile (AbstractBufferedFile ):
93+ """An fsspec buffered file implementation for the `pyscript` protocol."""
9094
95+ # `AbstractBufferedFile` protocol ##########################################
9196
92- class JFile (AbstractBufferedFile ):
9397 def _fetch_range (self , start , end ):
9498 return self .fs .cat_file (self .path , start , end )
9599
@@ -99,4 +103,5 @@ def _upload_chunk(self, final=False):
99103 return True
100104 return False
101105
106+
102107fsspec .register_implementation ("pyscript" , PyscriptFileSystem )
0 commit comments