1
1
# -*- coding: utf-8 -*-
2
2
import asyncio
3
3
import errno
4
+ import inspect
4
5
import logging
5
6
import mimetypes
6
7
import os
30
31
from aiobotocore .config import AioConfig
31
32
from botocore .exceptions import ClientError , HTTPClientError , ParamValidationError
32
33
from botocore .parsers import ResponseParserError
34
+ from botocore .credentials import create_credential_resolver
33
35
34
36
from s3fs .errors import translate_boto_error
35
37
from s3fs .utils import S3BucketRegionCache , ParamKwargsHelper , _get_brange , FileExpired
@@ -137,6 +139,18 @@ async def _error_wrapper(func, *, args=(), kwargs=None, retries):
137
139
except Exception as e :
138
140
err = e
139
141
err = translate_boto_error (err )
142
+
143
+ if inspect .ismethod (func ):
144
+ s3 = func .__self__
145
+ try :
146
+ is_anon = s3 ._client_config .signature_version == botocore .UNSIGNED
147
+ except AttributeError :
148
+ is_anon = False
149
+ if isinstance (err , PermissionError ) and is_anon :
150
+ raise PermissionError (
151
+ "Access failed in anonymous mode. You may need to provide credentials."
152
+ ) from err
153
+
140
154
raise err
141
155
142
156
@@ -464,6 +478,36 @@ async def set_session(self, refresh=False, kwargs={}):
464
478
return self ._s3
465
479
logger .debug ("Setting up s3fs instance" )
466
480
481
+ if self .session is None :
482
+ self .session = aiobotocore .session .AioSession (** self .kwargs )
483
+
484
+ drop_keys = {
485
+ "aws_access_key_id" ,
486
+ "aws_secret_access_key" ,
487
+ "aws_session_token" ,
488
+ }
489
+ if (
490
+ not self .anon
491
+ and (self .key or self .secret or self .token ) is None
492
+ and not drop_keys .intersection (set (self .client_kwargs ))
493
+ ):
494
+ # creating credentials resolver which enables loading credentials from configs/environment variables see
495
+ # https://github.com/boto/botocore/blob/develop/botocore/credentials.py#L2043
496
+ # tests whether any creds are available at all; if not, default to anonymous
497
+ cred_resolver = create_credential_resolver (
498
+ self .session , region_name = self .session ._last_client_region_used
499
+ )
500
+ credentials = cred_resolver .load_credentials ()
501
+
502
+ if credentials is None :
503
+ logger .debug ("No credentials given/found, setting `anon` to True." )
504
+ self .anon = True
505
+ else :
506
+ # by stashing these, we avoid doing the lookup again
507
+ self .key = credentials .access_key
508
+ self .secret = credentials .secret_key
509
+ self .token = credentials .token
510
+
467
511
client_kwargs = self .client_kwargs .copy ()
468
512
init_kwargs = dict (
469
513
aws_access_key_id = self .key ,
@@ -479,14 +523,10 @@ async def set_session(self, refresh=False, kwargs={}):
479
523
if "use_ssl" not in client_kwargs .keys ():
480
524
init_kwargs ["use_ssl" ] = self .use_ssl
481
525
config_kwargs = self ._prepare_config_kwargs ()
526
+
482
527
if self .anon :
483
528
from botocore import UNSIGNED
484
529
485
- drop_keys = {
486
- "aws_access_key_id" ,
487
- "aws_secret_access_key" ,
488
- "aws_session_token" ,
489
- }
490
530
init_kwargs = {
491
531
key : value for key , value in init_kwargs .items () if key not in drop_keys
492
532
}
@@ -498,8 +538,6 @@ async def set_session(self, refresh=False, kwargs={}):
498
538
config_kwargs ["signature_version" ] = UNSIGNED
499
539
500
540
conf = AioConfig (** config_kwargs )
501
- if self .session is None :
502
- self .session = aiobotocore .session .AioSession (** self .kwargs )
503
541
504
542
for parameters in (config_kwargs , self .kwargs , init_kwargs , client_kwargs ):
505
543
for option in ("region_name" , "endpoint_url" ):
0 commit comments