Skip to content

Commit 3f5a8d7

Browse files
authored
Revert anon fallback (#835)
* Revert "Don't assume attributes after connect (#832)" This reverts commit cc6663f. * Revert "Try anon=True if no credentials are supplied or found (#823)" This reverts commit 8a87309.
1 parent cc6663f commit 3f5a8d7

File tree

4 files changed

+43
-71
lines changed

4 files changed

+43
-71
lines changed

s3fs/core.py

+7-45
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# -*- coding: utf-8 -*-
22
import asyncio
33
import errno
4-
import inspect
54
import logging
65
import mimetypes
76
import os
@@ -31,7 +30,6 @@
3130
from aiobotocore.config import AioConfig
3231
from botocore.exceptions import ClientError, HTTPClientError, ParamValidationError
3332
from botocore.parsers import ResponseParserError
34-
from botocore.credentials import create_credential_resolver
3533

3634
from s3fs.errors import translate_boto_error
3735
from s3fs.utils import S3BucketRegionCache, ParamKwargsHelper, _get_brange, FileExpired
@@ -139,18 +137,6 @@ async def _error_wrapper(func, *, args=(), kwargs=None, retries):
139137
except Exception as e:
140138
err = e
141139
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-
154140
raise err
155141

156142

@@ -478,36 +464,6 @@ async def set_session(self, refresh=False, kwargs={}):
478464
return self._s3
479465
logger.debug("Setting up s3fs instance")
480466

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 = getattr(credentials, "access_key", None)
508-
self.secret = getattr(credentials, "secret_key", None)
509-
self.token = getattr(credentials, "token", None)
510-
511467
client_kwargs = self.client_kwargs.copy()
512468
init_kwargs = dict(
513469
aws_access_key_id=self.key,
@@ -523,10 +479,14 @@ async def set_session(self, refresh=False, kwargs={}):
523479
if "use_ssl" not in client_kwargs.keys():
524480
init_kwargs["use_ssl"] = self.use_ssl
525481
config_kwargs = self._prepare_config_kwargs()
526-
527482
if self.anon:
528483
from botocore import UNSIGNED
529484

485+
drop_keys = {
486+
"aws_access_key_id",
487+
"aws_secret_access_key",
488+
"aws_session_token",
489+
}
530490
init_kwargs = {
531491
key: value for key, value in init_kwargs.items() if key not in drop_keys
532492
}
@@ -538,6 +498,8 @@ async def set_session(self, refresh=False, kwargs={}):
538498
config_kwargs["signature_version"] = UNSIGNED
539499

540500
conf = AioConfig(**config_kwargs)
501+
if self.session is None:
502+
self.session = aiobotocore.session.AioSession(**self.kwargs)
541503

542504
for parameters in (config_kwargs, self.kwargs, init_kwargs, client_kwargs):
543505
for option in ("region_name", "endpoint_url"):

s3fs/tests/test_mapping.py

+16
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,22 @@ def test_with_data(s3):
5252
assert list(d) == []
5353

5454

55+
def test_complex_keys(s3):
56+
d = s3.get_mapper(root)
57+
d[1] = b"hello"
58+
assert d[1] == b"hello"
59+
del d[1]
60+
61+
d[1, 2] = b"world"
62+
assert d[1, 2] == b"world"
63+
del d[1, 2]
64+
65+
d["x", 1, 2] = b"hello world"
66+
assert d["x", 1, 2] == b"hello world"
67+
68+
assert ("x", 1, 2) in d
69+
70+
5571
def test_clear_empty(s3):
5672
d = s3.get_mapper(root)
5773
d.clear()

s3fs/tests/test_s3fs.py

-10
Original file line numberDiff line numberDiff line change
@@ -166,16 +166,6 @@ def test_simple(s3):
166166
assert out == data
167167

168168

169-
def test_auto_anon(s3, monkeypatch):
170-
monkeypatch.delenv("AWS_ACCESS_KEY_ID", raising=False)
171-
monkeypatch.delenv("AWS_SECRET_ACCESS_KEY", raising=False)
172-
monkeypatch.delenv("AWS_SESSION_TOKEN", raising=False)
173-
174-
fs = S3FileSystem(skip_instance_cache=True, endpoint_url=endpoint_uri)
175-
fs.s3
176-
assert fs.anon
177-
178-
179169
def test_with_size(s3):
180170
data = b"a" * (10 * 2**20)
181171

s3fs/utils.py

+20-16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import errno
22
import logging
33
from contextlib import contextmanager, AsyncExitStack
4+
from botocore.exceptions import ClientError
45

56

67
logger = logging.getLogger("s3fs")
@@ -30,13 +31,26 @@ async def get_bucket_client(self, bucket_name=None):
3031
if bucket_name in self._buckets:
3132
return self._buckets[bucket_name]
3233

34+
general_client = await self.get_client()
3335
if bucket_name is None:
34-
# general client
35-
return await self.get_client()
36-
37-
region = get_bucket_region(
38-
bucket_name
39-
) # this is sync - matters? can reuse some aiohttp session?
36+
return general_client
37+
38+
try:
39+
response = await general_client.head_bucket(Bucket=bucket_name)
40+
except ClientError as e:
41+
region = (
42+
e.response["ResponseMetadata"]
43+
.get("HTTPHeaders", {})
44+
.get("x-amz-bucket-region")
45+
)
46+
if not region:
47+
logger.debug(
48+
"RC: HEAD_BUCKET call for %r has failed, returning the general client",
49+
bucket_name,
50+
)
51+
return general_client
52+
else:
53+
region = response["ResponseMetadata"]["HTTPHeaders"]["x-amz-bucket-region"]
4054

4155
if region not in self._regions:
4256
logger.debug(
@@ -54,7 +68,6 @@ async def get_bucket_client(self, bucket_name=None):
5468
return client
5569

5670
async def get_client(self):
57-
# general, non-regional client
5871
if not self._client:
5972
self._client = await self._stack.enter_async_context(
6073
self._session.create_client("s3", **self._client_kwargs)
@@ -75,15 +88,6 @@ async def __aexit__(self, *exc_args):
7588
await self.clear()
7689

7790

78-
def get_bucket_region(bucket):
79-
"""Simple way to locate bucket"""
80-
import requests
81-
82-
return requests.head(f"https://s3.amazonaws.com/{bucket}").headers[
83-
"x-amz-bucket-region"
84-
]
85-
86-
8791
class FileExpired(IOError):
8892
"""
8993
Is raised, when the file content has been changed from a different process after

0 commit comments

Comments
 (0)