@@ -214,6 +214,13 @@ class S3FS(FS):
214214 :param str region: Optional S3 region.
215215 :param str delimiter: The delimiter to separate folders, defaults to
216216 a forward slash.
217+ :param bool strict: Validate correctness of the destination path.
218+ For example, throw exception FileExpected() when a directory
219+ path is supplied to ``setbinfile()`` method.
220+ These validations are quite expensive and normally can be
221+ safely disabled, assuming the client application doesn't mess
222+ with file paths intentionally.
223+ Defaults to ``True``.
217224
218225 """
219226
@@ -263,7 +270,8 @@ def __init__(self,
263270 aws_session_token = None ,
264271 endpoint_url = None ,
265272 region = None ,
266- delimiter = '/' ):
273+ delimiter = '/' ,
274+ strict = True ):
267275 _creds = (aws_access_key_id , aws_secret_access_key )
268276 if any (_creds ) and not all (_creds ):
269277 raise ValueError (
@@ -279,6 +287,7 @@ def __init__(self,
279287 self .endpoint_url = endpoint_url
280288 self .region = region
281289 self .delimiter = delimiter
290+ self .strict = strict
282291 self ._tlocal = threading .local ()
283292 super (S3FS , self ).__init__ ()
284293
@@ -529,9 +538,10 @@ def on_close_create(s3file):
529538
530539 return s3file
531540
532- info = self .getinfo (path )
533- if info .is_dir :
534- raise errors .FileExpected (path )
541+ if self .strict :
542+ info = self .getinfo (path )
543+ if info .is_dir :
544+ raise errors .FileExpected (path )
535545
536546 def on_close (s3file ):
537547 """Called when the S3 file closes, to upload the data."""
@@ -557,9 +567,10 @@ def remove(self, path):
557567 self .check ()
558568 _path = self .validatepath (path )
559569 _key = self ._path_to_key (_path )
560- info = self .getinfo (path )
561- if info .is_dir :
562- raise errors .FileExpected (path )
570+ if self .strict :
571+ info = self .getinfo (path )
572+ if info .is_dir :
573+ raise errors .FileExpected (path )
563574 self .client .delete_object (
564575 Bucket = self ._bucket_name ,
565576 Key = _key
@@ -681,14 +692,15 @@ def setbytes(self, path, contents):
681692
682693 _path = self .validatepath (path )
683694 _key = self ._path_to_key (_path )
684- if not self .isdir (dirname (path )):
685- raise errors .ResourceNotFound (path )
686- try :
687- info = self .getinfo (path )
688- if info .is_dir :
689- raise errors .FileExpected (path )
690- except errors .ResourceNotFound :
691- pass
695+ if self .strict :
696+ if not self .isdir (dirname (path )):
697+ raise errors .ResourceNotFound (path )
698+ try :
699+ info = self .getinfo (path )
700+ if info .is_dir :
701+ raise errors .FileExpected (path )
702+ except errors .ResourceNotFound :
703+ pass
692704
693705 bytes_file = io .BytesIO (contents )
694706 with s3errors (path ):
@@ -699,14 +711,16 @@ def setbytes(self, path, contents):
699711 def setbinfile (self , path , file ):
700712 _path = self .validatepath (path )
701713 _key = self ._path_to_key (_path )
702- if not self .isdir (dirname (path )):
703- raise errors .ResourceNotFound (path )
704- try :
705- info = self .getinfo (path )
706- if info .is_dir :
707- raise errors .FileExpected (path )
708- except errors .ResourceNotFound :
709- pass
714+
715+ if self .strict :
716+ if not self .isdir (dirname (path )):
717+ raise errors .ResourceNotFound (path )
718+ try :
719+ info = self .getinfo (path )
720+ if info .is_dir :
721+ raise errors .FileExpected (path )
722+ except errors .ResourceNotFound :
723+ pass
710724
711725 with s3errors (path ):
712726 self .client .upload_fileobj (file , self ._bucket_name , _key )
@@ -716,8 +730,9 @@ def copy(self, src_path, dst_path, overwrite=False):
716730 raise errors .DestinationExists (dst_path )
717731 _src_path = self .validatepath (src_path )
718732 _dst_path = self .validatepath (dst_path )
719- if not self .isdir (dirname (_dst_path )):
720- raise errors .ResourceNotFound (dst_path )
733+ if self .strict :
734+ if not self .isdir (dirname (_dst_path )):
735+ raise errors .ResourceNotFound (dst_path )
721736 _src_key = self ._path_to_key (_src_path )
722737 _dst_key = self ._path_to_key (_dst_path )
723738 try :
0 commit comments