Skip to content

Commit 01269ab

Browse files
authored
remove 3.5, better support 3.8, Pipfile (#769)
1 parent 9f004bd commit 01269ab

37 files changed

+259
-354
lines changed

.flake8

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[flake8]
2-
# Bump by 6 to account for "await " as compared to botocore
3-
max-line-length = 86
2+
# to match longest line in botocore: https://github.com/boto/botocore/blob/develop/botocore/client.py#L730
3+
max-line-length = 88

.pyup.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@
22
label_prs: deps-update
33

44
schedule: every week
5+
6+
requirements:
7+
- Pipfile
8+
- docs/requirements.txt

.travis.yml

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ python:
77
- 3.6.10
88
- 3.7.6
99
- 3.8.1
10-
# moto is incompatible with 3.5 because it relies on the key order of its regex rules
10+
# moto is incompatible with 3.5 because it relies on the key order of its url path regex rules
1111
# - 3.5.9
1212

1313
matrix:
@@ -18,16 +18,26 @@ matrix:
1818
env: EXTRA="boto3"
1919

2020
install:
21-
- pip install -U setuptools
22-
- if [[ -v EXTRA ]]; then pip install pipdeptree; fi
23-
- if ! [[ -v EXTRA ]]; then pip install -r requirements-dev.txt; fi
24-
- pip install codecov
25-
- pip freeze
21+
- pip install -U setuptools pip
22+
- if ! [[ -v EXTRA ]]; then
23+
pip install -U pipenv &&
24+
pipenv lock &&
25+
pipenv sync --dev &&
26+
pipenv check &&
27+
pipenv graph;
28+
else
29+
pip install codecov &&
30+
pip check &&
31+
pip freeze;
32+
fi
2633

2734
script:
28-
# requests from idna and docker packages conflicts with rest of the system...
29-
- if [[ -v EXTRA ]]; then pip install -U .[$EXTRA] && pipdeptree; fi
30-
- if ! [[ -v EXTRA ]]; then make flake mototest; fi
35+
- if [[ -v EXTRA ]]; then
36+
pip install -U pipdeptree .[$EXTRA] &&
37+
pipdeptree;
38+
else
39+
make flake mototest;
40+
fi
3141
after_success:
3242
codecov
3343
deploy:

CHANGES.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ Changes
33

44
0.12.0 (TBD)
55
^^^^^^^^^^^^
6-
76
* Bump botocore and extras
7+
* Drop support for 3.5 given we are unable to test it with moto
8+
and it will soon be unsupported
9+
* Remove loop parameters for Python 3.8 compliance
10+
* Remove deprecated AioPageIterator.next_page
811

912
0.11.1 (2020-01-03)
1013
^^^^^^^^^^^^^^^^^^^

CONTRIBUTING.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ For example using *virtualenvwrapper* commands could look like::
2222

2323
After that please install libraries required for development::
2424

25-
$ pip install -r requirements-dev.txt
26-
$ pip install -e .
25+
$ pipenv sync --dev
2726

2827
Congratulations, you are ready to run the test suite::
2928

@@ -78,7 +77,7 @@ versions that are compatible with the above changes.
7877
See next section describing types of changes we must validate and support.
7978

8079
Hashes of Botocore Code (important)
81-
-----------------------
80+
-----------------------------------
8281
Because of the way aiobotocore is implemented (see Background section), it is very tightly coupled with botocore. The validity of these couplings are enforced in test_patches.py. We also depend on some private properties in aiohttp, and because of this have entries in test_patches.py for this too.
8382

8483
These patches are important to catch cases where botocore functionality was added/removed and needs to be reflected in our overridden methods. Changes include:

Makefile

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,24 @@
33
FLAGS=
44

55
flake: checkrst
6-
python3 -m flake8 --format=abspath
6+
pipenv run python3 -m flake8 --format=abspath
77

88
test: flake
9-
python3 -m pytest -s $(FLAGS) ./tests/
9+
pipenv run python3 -Wd -m pytest -s -vv $(FLAGS) ./tests/
1010

1111
vtest:
12-
python3 -m pytest -s -v $(FLAGS) ./tests/
12+
pipenv run python3 -Wd -X tracemalloc=5 -X faulthandler -m pytest -s -vv $(FLAGS) ./tests/
1313

1414
checkrst:
15-
python3 setup.py check -rms
15+
pipenv run python3 setup.py check -rms
1616

1717
cov cover coverage: flake
18-
python3 -m pytest -s -v --cov-report term --cov-report html --cov aiobotocore ./tests
18+
pipenv run python3 -Wd -m pytest -s -vv --cov-report term --cov-report html --cov aiobotocore ./tests
1919
@echo "open file://`pwd`/htmlcov/index.html"
2020

2121
# BOTO_CONFIG solves https://github.com/travis-ci/travis-ci/issues/7940
2222
mototest:
23-
BOTO_CONFIG=/dev/null python3 -m pytest -v -m moto -n auto --cov-report term --cov-report html --cov aiobotocore tests
23+
BOTO_CONFIG=/dev/null pipenv run python3 -Wd -X tracemalloc=5 -X faulthandler -m pytest -vv -m moto -n auto --cov-report term --cov-report html --cov aiobotocore tests
2424
@echo "open file://`pwd`/htmlcov/index.html"
2525

2626

Pipfile

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[[source]]
2+
name = "pypi"
3+
url = "https://pypi.org/simple"
4+
verify_ssl = true
5+
6+
[dev-packages]
7+
codecov = "*"
8+
coverage = "==5.0.3"
9+
flake8 = "==3.7.9"
10+
flake8-formatter-abspath = "==1.0.1"
11+
moto = {extras = ["server"],version = "==1.3.14"}
12+
pytest = "==5.3.5"
13+
pytest-cov = "==2.8.1"
14+
pytest-asyncio = "==0.10.0"
15+
pytest-xdist = "==1.31.0"
16+
dill = "==0.3.1.1"
17+
18+
# for some reason this is needed when running setup.py check -rms on travis on 3.6.10
19+
Pygments = "*"
20+
21+
[packages]
22+
aiohttp = "==3.3.2"
23+
aiobotocore = {editable = true,extras = ["awscli", "boto3"],path = "."}

README.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ Basic Example
4242
AWS_SECRET_ACCESS_KEY = "xxx"
4343
4444
45-
async def go(loop):
45+
async def go():
4646
bucket = 'dataintake'
4747
filename = 'dummy.bin'
4848
folder = 'aiobotocore'
4949
key = '{}/{}'.format(folder, filename)
5050
51-
session = aiobotocore.get_session(loop=loop)
51+
session = aiobotocore.get_session()
5252
async with session.create_client('s3', region_name='us-west-2',
5353
aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
5454
aws_access_key_id=AWS_ACCESS_KEY_ID) as client:
@@ -80,7 +80,7 @@ Basic Example
8080
print(resp)
8181
8282
loop = asyncio.get_event_loop()
83-
loop.run_until_complete(go(loop))
83+
loop.run_until_complete(go())
8484
8585
8686
Supported AWS Services
@@ -121,7 +121,7 @@ secret accessible via environment variables:
121121
$ cd aiobotocore
122122
$ export AWS_ACCESS_KEY_ID=xxx
123123
$ export AWS_SECRET_ACCESS_KEY=xxx
124-
$ pip install -Ur requirements-dev.txt
124+
$ pipenv sync --dev
125125

126126
Execute tests suite:
127127

aiobotocore/args.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import asyncio
21
import copy
3-
import botocore.args
2+
3+
from botocore.args import ClientArgsCreator
44
import botocore.serialize
55
import botocore.parsers
66
from botocore.signers import RequestSigner
@@ -9,11 +9,7 @@
99
from .endpoint import AioEndpointCreator
1010

1111

12-
class AioClientArgsCreator(botocore.args.ClientArgsCreator):
13-
def __init__(self, *args, loop=None, **kwargs):
14-
super().__init__(*args, **kwargs)
15-
self._loop = loop or asyncio.get_event_loop()
16-
12+
class AioClientArgsCreator(ClientArgsCreator):
1713
# NOTE: we override this so we can pull out the custom AioConfig params and
1814
# use an AioEndpointCreator
1915
def get_client_args(self, service_model, region_name, is_secure,
@@ -45,13 +41,14 @@ def get_client_args(self, service_model, region_name, is_secure,
4541

4642
config_kwargs['s3'] = s3_config
4743

44+
# aiobotocore addition
4845
if isinstance(client_config, AioConfig):
4946
connector_args = client_config.connector_args
5047
else:
5148
connector_args = None
5249

5350
new_config = AioConfig(connector_args, **config_kwargs)
54-
endpoint_creator = AioEndpointCreator(event_emitter, loop=self._loop)
51+
endpoint_creator = AioEndpointCreator(event_emitter)
5552

5653
endpoint = endpoint_creator.create_endpoint(
5754
service_model, region_name=endpoint_region_name,
@@ -77,6 +74,5 @@ def get_client_args(self, service_model, region_name, is_secure,
7774
'loader': self._loader,
7875
'client_config': new_config,
7976
'partition': partition,
80-
'exceptions_factory': self._exceptions_factory,
81-
'loop': self._loop
77+
'exceptions_factory': self._exceptions_factory
8278
}

aiobotocore/client.py

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import asyncio
2-
31
from botocore.client import logger, PaginatorDocstring, ClientCreator, BaseClient
42
from botocore.exceptions import OperationNotPageableError
53
from botocore.history import get_global_history_recorder
@@ -15,11 +13,6 @@
1513

1614

1715
class AioClientCreator(ClientCreator):
18-
19-
def __init__(self, *args, loop=None, **kwargs):
20-
super().__init__(*args, **kwargs)
21-
self._loop = loop or asyncio.get_event_loop()
22-
2316
def _create_client_class(self, service_name, service_model):
2417
class_attributes = self._create_methods(service_model)
2518
py_name_to_operation_name = self._create_name_mapping(service_model)
@@ -42,18 +35,13 @@ def _get_client_args(self, service_model, region_name, is_secure,
4235
args_creator = AioClientArgsCreator(
4336
self._event_emitter, self._user_agent,
4437
self._response_parser_factory, self._loader,
45-
self._exceptions_factory, config_store=self._config_store,
46-
loop=self._loop)
38+
self._exceptions_factory, config_store=self._config_store)
4739
return args_creator.get_client_args(
4840
service_model, region_name, is_secure, endpoint_url,
4941
verify, credentials, scoped_config, client_config, endpoint_bridge)
5042

5143

5244
class AioBaseClient(BaseClient):
53-
def __init__(self, *args, **kwargs):
54-
self._loop = kwargs.pop('loop', None) or asyncio.get_event_loop()
55-
super().__init__(*args, **kwargs)
56-
5745
async def _make_api_call(self, operation_name, api_params):
5846
operation_model = self._service_model.operation_model(operation_name)
5947
service_name = self._service_model.service_name
@@ -103,11 +91,9 @@ async def _make_api_call(self, operation_name, api_params):
10391
else:
10492
return parsed_response
10593

106-
async def _make_request(self, operation_model, request_dict,
107-
request_context):
94+
async def _make_request(self, operation_model, request_dict, request_context):
10895
try:
109-
return await self._endpoint.make_request(operation_model,
110-
request_dict)
96+
return await self._endpoint.make_request(operation_model, request_dict)
11197
except Exception as e:
11298
self.meta.events.emit(
11399
'after-call-error.{service_id}.{operation_name}'.format(
@@ -167,14 +153,15 @@ def paginate(self, **kwargs):
167153
documented_paginator_cls = type(
168154
paginator_class_name, (AioPaginator,), {'paginate': paginate})
169155

170-
operation_model = self._service_model.operation_model(
171-
actual_operation_name)
156+
operation_model = self._service_model.operation_model(actual_operation_name)
172157
paginator = documented_paginator_cls(
173158
getattr(self, operation_name),
174159
paginator_config,
175160
operation_model)
176161
return paginator
177162

163+
# NOTE: this method does not differ from botocore, however it's important to keep
164+
# as the "waiter" value points to our own asyncio waiter module
178165
def get_waiter(self, waiter_name):
179166
"""Returns an object that can wait for some condition.
180167
@@ -196,7 +183,7 @@ def get_waiter(self, waiter_name):
196183
raise ValueError("Waiter does not exist: %s" % waiter_name)
197184

198185
return waiter.create_waiter_with_client(
199-
mapping[waiter_name], model, self, loop=self._loop)
186+
mapping[waiter_name], model, self)
200187

201188
async def __aenter__(self):
202189
await self._endpoint.http_session.__aenter__()

aiobotocore/endpoint.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,8 @@ async def convert_to_response_dict(http_response, operation_model):
5959

6060

6161
class AioEndpoint(Endpoint):
62-
def __init__(self, *args, loop=None, proxies=None, **kwargs):
62+
def __init__(self, *args, proxies=None, **kwargs):
6363
super().__init__(*args, **kwargs)
64-
65-
self._loop = loop or asyncio.get_event_loop()
6664
self.proxies = proxies or {}
6765

6866
async def _send_request(self, request_dict, operation_model):
@@ -184,7 +182,7 @@ async def _needs_retry(self, attempts, operation_model, request_dict,
184182
# for the specified number of times.
185183
logger.debug("Response received to retry, sleeping for "
186184
"%s seconds", handler_response)
187-
await asyncio.sleep(handler_response, loop=self._loop)
185+
await asyncio.sleep(handler_response)
188186
return True
189187

190188
async def _send(self, request):
@@ -229,10 +227,6 @@ async def _send(self, request):
229227

230228

231229
class AioEndpointCreator(EndpointCreator):
232-
def __init__(self, *args, loop=None, **kwargs):
233-
super().__init__(*args, **kwargs)
234-
self._loop = loop
235-
236230
# TODO: handle socket_options
237231
def create_endpoint(self, service_model, region_name, endpoint_url,
238232
verify=None, response_parser_factory=None,
@@ -282,7 +276,6 @@ def create_endpoint(self, service_model, region_name, endpoint_url,
282276
ssl_context.load_cert_chain(cert_file, key_file)
283277

284278
connector = aiohttp.TCPConnector(
285-
loop=self._loop,
286279
limit=max_pool_connections,
287280
verify_ssl=self._get_verify_value(verify),
288281
ssl_context=ssl_context,
@@ -293,7 +286,6 @@ def create_endpoint(self, service_model, region_name, endpoint_url,
293286
timeout=timeout,
294287
skip_auto_headers={'CONTENT-TYPE'},
295288
response_class=ClientResponseProxy,
296-
loop=self._loop,
297289
auto_decompress=False)
298290

299291
return AioEndpoint(
@@ -302,4 +294,4 @@ def create_endpoint(self, service_model, region_name, endpoint_url,
302294
event_emitter=self._event_emitter,
303295
response_parser_factory=response_parser_factory,
304296
http_session=aio_session,
305-
loop=self._loop, proxies=proxies)
297+
proxies=proxies)

aiobotocore/eventstream.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,22 @@
11
from botocore.eventstream import EventStream, EventStreamBuffer
2-
from async_generator import async_generator, yield_
32

43

54
class AioEventStream(EventStream):
6-
@async_generator
75
async def _create_raw_event_generator(self):
86
event_stream_buffer = EventStreamBuffer()
97
async for chunk, _ in self._raw_stream.iter_chunks():
108
event_stream_buffer.add_data(chunk)
119
for event in event_stream_buffer:
12-
await yield_(event)
10+
yield event
1311

1412
def __iter__(self):
1513
raise NotImplementedError('Use async-for instead')
1614

1715
def __aiter__(self):
1816
return self.__anext__()
1917

20-
@async_generator
2118
async def __anext__(self):
2219
async for event in self._event_generator:
2320
parsed_event = self._parse_event(event)
2421
if parsed_event:
25-
await yield_(parsed_event)
22+
yield parsed_event

0 commit comments

Comments
 (0)