@@ -161,34 +161,6 @@ class S3FileSystem(AbstractFileSystem):
161161 """
162162
163163 DEFAULT_BLOCK_SIZE : int = 5 * 2 ** 20 # 5MiB
164- # https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html#canned-acl
165- OBJECT_ACLS : frozenset [str ] = frozenset (
166- {
167- "private" ,
168- "public-read" ,
169- "public-read-write" ,
170- "authenticated-read" ,
171- "aws-exec-read" ,
172- "bucket-owner-read" ,
173- "bucket-owner-full-control" ,
174- }
175- )
176- BUCKET_ACLS : frozenset [str ] = frozenset (
177- {"private" , "public-read" , "public-read-write" , "authenticated-read" }
178- )
179- # https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html
180- # The CopyObject parameters that set the encryption of the copy.
181- _SSE_COPY_PARAMS : frozenset [str ] = frozenset (
182- {
183- "ServerSideEncryption" ,
184- "SSEKMSKeyId" ,
185- "SSEKMSEncryptionContext" ,
186- "BucketKeyEnabled" ,
187- "SSECustomerAlgorithm" ,
188- "SSECustomerKey" ,
189- "SSECustomerKeyMD5" ,
190- }
191- )
192164 PATTERN_PATH : Pattern [str ] = S3Path .PATTERN
193165
194166 protocol = ("s3" , "s3a" )
@@ -1282,8 +1254,8 @@ def mkdir(self, path: str, create_parents: bool = True, **kwargs) -> None:
12821254 "Set allow_bucket_creation=True on the filesystem to enable it."
12831255 )
12841256 acl = kwargs .pop ("acl" , "" )
1285- if acl and acl not in self .BUCKET_ACLS :
1286- raise ValueError (f"ACL not in { self .BUCKET_ACLS } ." )
1257+ if acl and acl not in self .core . BUCKET_ACLS :
1258+ raise ValueError (f"ACL not in { self .core . BUCKET_ACLS } ." )
12871259 request : dict [str , Any ] = {"Bucket" : s3_path .bucket }
12881260 if acl :
12891261 request .update ({"ACL" : acl })
@@ -2197,23 +2169,9 @@ def sign(self, path: str, expiration: int = 3600, **kwargs):
21972169 ... client_method="put_object"
21982170 ... )
21992171 """
2200- s3_path = S3Path .parse (path )
22012172 client_method = kwargs .pop ("client_method" , "get_object" )
2202- params = {"Bucket" : s3_path .bucket , "Key" : s3_path .key }
2203- if s3_path .version_id :
2204- params .update ({"VersionId" : s3_path .version_id })
2205- if kwargs :
2206- params .update (kwargs )
2207- request = {
2208- "ClientMethod" : client_method ,
2209- "Params" : params ,
2210- "ExpiresIn" : expiration ,
2211- }
2212-
2213- _logger .debug (f"Generate signed url: { s3_path .uri } " )
2214- return self ._call (
2215- self ._client .generate_presigned_url ,
2216- ** request ,
2173+ return self .core .generate_presigned_url (
2174+ S3Path .parse (path ), client_method , expiration , ** kwargs
22172175 )
22182176
22192177 def metadata (self , path : str , ** kwargs ) -> S3Metadata :
@@ -2295,43 +2253,7 @@ def setxattr(self, path: str, copy_kwargs: dict[str, Any] | None = None, **kw_ar
22952253 metadata .pop (k , None )
22962254 else :
22972255 metadata [k ] = v
2298-
2299- # With the REPLACE directive, S3 does not copy what the request
2300- # omits: the system-defined metadata is dropped, and the copy is
2301- # written as STANDARD with the default encryption of the bucket.
2302- kept : dict [str , Any ] = {
2303- "CacheControl" : head .cache_control ,
2304- "ContentDisposition" : head .content_disposition ,
2305- "ContentEncoding" : head .content_encoding ,
2306- "ContentLanguage" : head .content_language ,
2307- "ContentType" : head .content_type ,
2308- "Expires" : head .expires ,
2309- "WebsiteRedirectLocation" : head .website_redirect_location ,
2310- "StorageClass" : head .storage_class ,
2311- }
2312- copy_kwargs = copy_kwargs if copy_kwargs else {}
2313- if not self ._SSE_COPY_PARAMS .intersection (copy_kwargs ):
2314- kept .update (
2315- {
2316- "ServerSideEncryption" : head .server_side_encryption ,
2317- "SSEKMSKeyId" : head .sse_kms_key_id ,
2318- "BucketKeyEnabled" : head .bucket_key_enabled ,
2319- }
2320- )
2321-
2322- _logger .debug (f"Set object metadata: { s3_path .uri } " )
2323- self ._call (
2324- self ._client .copy_object ,
2325- CopySource = {"Bucket" : s3_path .bucket , "Key" : s3_path .key },
2326- Bucket = s3_path .bucket ,
2327- Key = s3_path .key ,
2328- Metadata = metadata ,
2329- MetadataDirective = "REPLACE" ,
2330- ** {
2331- ** {k : v for k , v in kept .items () if v is not None },
2332- ** copy_kwargs ,
2333- },
2334- )
2256+ self .core .replace_object_metadata (s3_path , head , metadata , ** (copy_kwargs or {}))
23352257 self .invalidate_cache (path )
23362258
23372259 def get_tags (self , path : str ) -> dict [str , str ]:
@@ -2346,16 +2268,7 @@ def get_tags(self, path: str) -> dict[str, str]:
23462268 s3_path = S3Path .parse (path )
23472269 if not s3_path .key :
23482270 raise ValueError ("Cannot get tags of a bucket." )
2349- request : dict [str , Any ] = {"Bucket" : s3_path .bucket , "Key" : s3_path .key }
2350- if s3_path .version_id :
2351- request .update ({"VersionId" : s3_path .version_id })
2352-
2353- _logger .debug (f"Get object tagging: { s3_path .uri } " )
2354- response = self ._call (
2355- self ._client .get_object_tagging ,
2356- ** request ,
2357- )
2358- return {v ["Key" ]: v ["Value" ] for v in response ["TagSet" ]}
2271+ return self .core .get_object_tagging (s3_path )
23592272
23602273 def put_tags (self , path : str , tags : dict [str , str ], mode : str = "o" ) -> None :
23612274 """Set the tags for the given existing key.
@@ -2377,26 +2290,12 @@ def put_tags(self, path: str, tags: dict[str, str], mode: str = "o") -> None:
23772290 if not s3_path .key :
23782291 raise ValueError ("Cannot put tags of a bucket." )
23792292 if mode == "m" :
2380- existing_tags = self .get_tags (path )
2381- existing_tags .update (tags )
2382- new_tags = [{"Key" : k , "Value" : v } for k , v in existing_tags .items ()]
2293+ new_tags = {** self .core .get_object_tagging (s3_path ), ** tags }
23832294 elif mode == "o" :
2384- new_tags = [{ "Key" : k , "Value" : v } for k , v in tags . items ()]
2295+ new_tags = tags
23852296 else :
23862297 raise ValueError (f"Mode must be {{'o', 'm'}}, not { mode } ." )
2387- request : dict [str , Any ] = {
2388- "Bucket" : s3_path .bucket ,
2389- "Key" : s3_path .key ,
2390- "Tagging" : {"TagSet" : new_tags },
2391- }
2392- if s3_path .version_id :
2393- request .update ({"VersionId" : s3_path .version_id })
2394-
2395- _logger .debug (f"Put object tagging: { s3_path .uri } " )
2396- self ._call (
2397- self ._client .put_object_tagging ,
2398- ** request ,
2399- )
2298+ self .core .put_object_tagging (s3_path , new_tags )
24002299
24012300 def chmod (self , path : str , acl : str , recursive : bool = False , ** kwargs ) -> None :
24022301 """Set the Access Control on a bucket/key.
@@ -2414,10 +2313,10 @@ def chmod(self, path: str, acl: str, recursive: bool = False, **kwargs) -> None:
24142313 s3_path = S3Path .parse (path )
24152314 # Validate before any ACL is applied so that a recursive call cannot
24162315 # partially apply object ACLs and then fail on the bucket ACL.
2417- if not s3_path .key and acl not in self .BUCKET_ACLS :
2418- raise ValueError (f"ACL not in { self .BUCKET_ACLS } ." )
2419- if s3_path .key and acl not in self .OBJECT_ACLS :
2420- raise ValueError (f"ACL not in { self .OBJECT_ACLS } ." )
2316+ if not s3_path .key and acl not in self .core . BUCKET_ACLS :
2317+ raise ValueError (f"ACL not in { self .core . BUCKET_ACLS } ." )
2318+ if s3_path .key and acl not in self .core . OBJECT_ACLS :
2319+ raise ValueError (f"ACL not in { self .core . OBJECT_ACLS } ." )
24212320 if recursive :
24222321 with self ._create_executor (max_workers = self .max_workers ) as executor :
24232322 futures = [
@@ -2431,24 +2330,9 @@ def chmod(self, path: str, acl: str, recursive: bool = False, **kwargs) -> None:
24312330 # below it have ACLs.
24322331 return
24332332 if s3_path .key :
2434- request : dict [str , Any ] = {"Bucket" : s3_path .bucket , "Key" : s3_path .key , "ACL" : acl }
2435- if s3_path .version_id :
2436- request .update ({"VersionId" : s3_path .version_id })
2437-
2438- _logger .debug (f"Put object acl: { s3_path .uri } " )
2439- self ._call (
2440- self ._client .put_object_acl ,
2441- ** request ,
2442- ** kwargs ,
2443- )
2333+ self .core .put_object_acl (s3_path , acl , ** kwargs )
24442334 else :
2445- _logger .debug (f"Put bucket acl: { s3_path .uri } " )
2446- self ._call (
2447- self ._client .put_bucket_acl ,
2448- Bucket = s3_path .bucket ,
2449- ACL = acl ,
2450- ** kwargs ,
2451- )
2335+ self .core .put_bucket_acl (s3_path .bucket , acl , ** kwargs )
24522336
24532337 def list_multipart_uploads (self , path : str ) -> list [S3MultipartUpload ]:
24542338 """List in-progress (incomplete) multipart uploads in a bucket.
0 commit comments