Skip to content

Commit

Permalink
Merge branch 'master' into split_out
Browse files Browse the repository at this point in the history
  • Loading branch information
jakkdl authored Mar 20, 2024
2 parents 3699568 + e8a3b8e commit d70635f
Show file tree
Hide file tree
Showing 12 changed files with 103 additions and 79 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
make mototest
- name: Upload coverage to Codecov
if: matrix.python-version == '3.11'
uses: codecov/codecov-action@v3.1.5
uses: codecov/codecov-action@v4.1.0
with:
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos
files: ./coverage.xml
Expand Down
17 changes: 17 additions & 0 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: 2

build:
os: ubuntu-22.04
tools:
python: "3.8"

sphinx:
configuration: docs/conf.py

python:
install:
- requirements: docs/requirements.txt

formats:
- htmlzip
- epub
8 changes: 8 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Changes
-------

2.12.1 (2024-03-04)
^^^^^^^^^^^^^^^^^^^
* fix use of proxies #1070

2.12.0 (2024-02-28)
^^^^^^^^^^^^^^^^^^^
* bump botocore dependency specification

2.11.2 (2024-02-02)
^^^^^^^^^^^^^^^^^^^
* bump botocore dependency specification
Expand Down
2 changes: 1 addition & 1 deletion aiobotocore/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '2.11.2'
__version__ = '2.12.1'
6 changes: 3 additions & 3 deletions aiobotocore/credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -914,8 +914,7 @@ async def _retrieve_or_fail(self):
full_uri = self._fetcher.full_url(self._environ[self.ENV_VAR])
else:
full_uri = self._environ[self.ENV_VAR_FULL]
headers = self._build_headers()
fetcher = self._create_fetcher(full_uri, headers)
fetcher = self._create_fetcher(full_uri)
creds = await fetcher()
return AioRefreshableCredentials(
access_key=creds['access_key'],
Expand All @@ -926,9 +925,10 @@ async def _retrieve_or_fail(self):
refresh_using=fetcher,
)

def _create_fetcher(self, full_uri, headers):
def _create_fetcher(self, full_uri, *args, **kwargs):
async def fetch_creds():
try:
headers = self._build_headers()
response = await self._fetcher.retrieve_full_uri(
full_uri, headers=headers
)
Expand Down
113 changes: 64 additions & 49 deletions aiobotocore/httpsession.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import asyncio
import contextlib
import io
import os
import socket
Expand Down Expand Up @@ -54,8 +55,11 @@ def __init__(
proxies_config=None,
connector_args=None,
):
self._exit_stack = contextlib.AsyncExitStack()

# TODO: handle socket_options
self._session: Optional[aiohttp.ClientSession] = None
# keep track of sessions by proxy url (if any)
self._sessions: Dict[Optional[str], aiohttp.ClientSession] = {}
self._verify = verify
self._proxy_config = ProxyConfiguration(
proxies=proxies, proxies_settings=proxies_config
Expand Down Expand Up @@ -93,53 +97,17 @@ def __init__(
# it also pools by host so we don't need a manager, and can pass proxy via
# request so don't need proxy manager

ssl_context = None
if bool(verify):
if proxies:
proxies_settings = self._proxy_config.settings
ssl_context = self._setup_proxy_ssl_context(proxies_settings)
# TODO: add support for
# proxies_settings.get('proxy_use_forwarding_for_https')
else:
ssl_context = self._get_ssl_context()

# inline self._setup_ssl_cert
ca_certs = get_cert_path(verify)
if ca_certs:
ssl_context.load_verify_locations(ca_certs, None, None)

self._create_connector = lambda: aiohttp.TCPConnector(
limit=max_pool_connections,
verify_ssl=bool(verify),
ssl=ssl_context,
**self._connector_args
)
self._connector = None

async def __aenter__(self):
assert not self._session and not self._connector
assert not self._sessions

self._connector = self._create_connector()

self._session = aiohttp.ClientSession(
connector=self._connector,
timeout=self._timeout,
skip_auto_headers={'CONTENT-TYPE'},
auto_decompress=False,
)
return self

async def __aexit__(self, exc_type, exc_val, exc_tb):
if self._session:
await self._session.__aexit__(exc_type, exc_val, exc_tb)
self._session = None
self._connector = None
self._sessions.clear()
await self._exit_stack.aclose()

def _get_ssl_context(self):
ssl_context = create_urllib3_context()
if self._cert_file:
ssl_context.load_cert_chain(self._cert_file, self._key_file)
return ssl_context
return create_urllib3_context()

def _setup_proxy_ssl_context(self, proxy_url):
proxies_settings = self._proxy_config.settings
Expand Down Expand Up @@ -167,6 +135,58 @@ def _setup_proxy_ssl_context(self, proxy_url):
except (OSError, LocationParseError) as e:
raise InvalidProxiesConfigError(error=e)

def _chunked(self, headers):
transfer_encoding = headers.get('Transfer-Encoding', '')
if chunked := transfer_encoding.lower() == 'chunked':
# aiohttp wants chunking as a param, and not a header
del headers['Transfer-Encoding']
return chunked or None

def _create_connector(self, proxy_url):
ssl_context = None
if bool(self._verify):
if proxy_url:
ssl_context = self._setup_proxy_ssl_context(proxy_url)
# TODO: add support for
# proxies_settings.get('proxy_use_forwarding_for_https')
else:
ssl_context = self._get_ssl_context()

if ssl_context:
if self._cert_file:
ssl_context.load_cert_chain(
self._cert_file,
self._key_file,
)

# inline self._setup_ssl_cert
ca_certs = get_cert_path(self._verify)
if ca_certs:
ssl_context.load_verify_locations(ca_certs, None, None)

return aiohttp.TCPConnector(
limit=self._max_pool_connections,
verify_ssl=bool(self._verify),
ssl=ssl_context,
**self._connector_args,
)

async def _get_session(self, proxy_url):
if not (session := self._sessions.get(proxy_url)):
connector = self._create_connector(proxy_url)
self._sessions[
proxy_url
] = session = await self._exit_stack.enter_async_context(
aiohttp.ClientSession(
connector=connector,
timeout=self._timeout,
skip_auto_headers={'CONTENT-TYPE'},
auto_decompress=False,
),
)

return session

async def close(self):
await self.__aexit__(None, None, None)

Expand Down Expand Up @@ -195,20 +215,15 @@ async def send(self, request):
# https://github.com/boto/botocore/issues/1255
headers_['Accept-Encoding'] = 'identity'

chunked = None
if headers_.get('Transfer-Encoding', '').lower() == 'chunked':
# aiohttp wants chunking as a param, and not a header
headers_.pop('Transfer-Encoding', '')
chunked = True

if isinstance(data, io.IOBase):
data = _IOBaseWrapper(data)

url = URL(url, encoded=True)
response = await self._session.request(
session = await self._get_session(proxy_url)
response = await session.request(
request.method,
url=url,
chunked=chunked,
chunked=self._chunked(headers_),
headers=headers_,
data=data,
proxy=proxy_url,
Expand Down
6 changes: 1 addition & 5 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
language = "en"

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
Expand Down Expand Up @@ -123,10 +123,6 @@
'github_type': 'star',
'github_banner': True,
}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']


# -- Options for HTMLHelp output ------------------------------------------
Expand Down
3 changes: 2 additions & 1 deletion docs/examples/s3/basic_usage.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Put, Get and Delete
-----------
-------------------

Simple put, get, delete example for S3 service:

.. literalinclude:: ../../../examples/simple.py
2 changes: 1 addition & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sphinx==2.4.1
sphinx==5.3.0
11 changes: 0 additions & 11 deletions readthedocs.yml

This file was deleted.

6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
# NOTE: When updating botocore make sure to update awscli/boto3 versions below
install_requires = [
# pegged to also match items in `extras_require`
'botocore>=1.33.2,<1.34.35',
'botocore>=1.34.41,<1.34.52',
'aiohttp>=3.7.4.post0,<4.0.0',
'wrapt>=1.10.10, <2.0.0',
'aioitertools>=0.5.1,<1.0.0',
]

extras_require = {
'awscli': ['awscli>=1.31.2,<1.32.35'],
'boto3': ['boto3>=1.33.2,<1.34.35'],
'awscli': ['awscli>=1.32.41,<1.32.52'],
'boto3': ['boto3>=1.34.41,<1.34.52'],
}


Expand Down
6 changes: 2 additions & 4 deletions tests/test_patches.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,9 @@
'f09731451ff6ba0645dc82e5c7948dfbf781e025',
},
BaseClient.get_paginator: {
'3531d5988aaaf0fbb3885044ccee1a693ec2608b',
'1c38079de68ccd43a5a06e36b1a47ec62233a7c2',
},
BaseClient.get_waiter: {
'44f0473d993d49ac7502984a7ccee3240b088404',
'4a4aeabe53af25d3737204187a31f930230864b4',
},
BaseClient.__getattr__: {'3ec17f468f50789fa633d6041f40b66a2f593e77'},
Expand Down Expand Up @@ -266,10 +264,10 @@
ContainerProvider.__init__: {'ea6aafb2e12730066af930fb5a27f7659c1736a1'},
ContainerProvider.load: {'57c35569050b45c1e9e33fcdb3b49da9e342fdcf'},
ContainerProvider._retrieve_or_fail: {
'7c14f1cdee07217f847a71068866bdd10c3fa0fa'
'c99153a4c68927810a3edde09ee98c5ba33d3697'
},
ContainerProvider._create_fetcher: {
'935ae28fdb1c76f419523d4030265f8c4d9d0b00'
'a921ee40b9b4779f238adcf369a3757b19857fc7'
},
InstanceMetadataProvider.load: {
'15becfc0373ccfbc1bb200bd6a34731e61561d06'
Expand Down

0 comments on commit d70635f

Please sign in to comment.