@@ -70,6 +70,13 @@ def __init__(self, f, filename, mode, on_close=None):
7070 self .__mode = mode
7171 self ._on_close = on_close
7272
73+
74+ def __enter__ (self ):
75+ return self
76+
77+ def __exit__ (self , exc_type , exc_value , traceback ):
78+ self .close
79+
7380 def close (self ):
7481 print ("Close" )
7582 if self ._on_close is not None :
@@ -79,6 +86,22 @@ def __getattr__(self, key):
7986 return getattr (self ._f , key )
8087
8188
89+ class S3ClientErrors (object ):
90+
91+ def __init__ (self , path ):
92+ self .path = path
93+
94+ def __enter__ (self ):
95+ return self
96+
97+ def __exit__ (self , exc_type , exc_value , traceback ):
98+ if exc_type is ClientError :
99+ error = exc_value
100+ error_code = int (error .response ['Error' ]['Code' ])
101+ if error_code == 404 :
102+ raise errors .ResourceNotFound (self .path )
103+
104+
82105@six .python_2_unicode_compatible
83106class S3FS (FS ):
84107
@@ -184,6 +207,20 @@ def getinfo(self, path, namespaces=None):
184207 _path = self .validatepath (path )
185208 _key = self ._path_to_key (_path )
186209
210+ if _path == '/' :
211+ return Info ({
212+ "basic" :
213+ {
214+ "name" : "" ,
215+ "is_dir" : True
216+ },
217+ "details" :
218+ {
219+ "type" : int (ResourceType .directory )
220+ }
221+ })
222+
223+
187224 obj = self ._get_object (path , _key )
188225
189226 name = basename (self ._key_to_path (_key ))
@@ -278,8 +315,13 @@ def on_close(proxy_file):
278315
279316 proxy_file = S3File .factory (path , _mode , on_close = on_close )
280317 if _mode .appending :
281- self .client .download_fileobj (self ._bucket_name , _key , proxy_file )
282- proxy_file .seek (0 , os .SEEK_END )
318+ try :
319+ with S3ClientErrors (path ):
320+ self .client .download_fileobj (self ._bucket_name , _key , proxy_file )
321+ except errors .ResourceNotFound :
322+ pass
323+ else :
324+ proxy_file .seek (0 , os .SEEK_END )
283325
284326 return proxy_file
285327
@@ -294,7 +336,8 @@ def on_close(proxy_file):
294336 return True
295337
296338 proxy_file = S3File .factory (path , _mode , on_close = on_close )
297- self .client .download_fileobj (self ._bucket_name , _key , proxy_file )
339+ with S3ClientErrors (path ):
340+ self .client .download_fileobj (self ._bucket_name , _key , proxy_file )
298341 proxy_file .seek (0 , os .SEEK_SET )
299342
300343 return proxy_file
@@ -314,7 +357,7 @@ def remove(self, path):
314357
315358 def isempty (self , path ):
316359 self .check ()
317- _path = self .validatepath ()
360+ _path = self .validatepath (path )
318361 _key = self ._path_to_key (_path )
319362 response = self .client .list_objects (
320363 Bucket = self ._bucket_name ,
0 commit comments