Skip to content

Commit 28f96b7

Browse files
authored
Typing (#37)
* Bump to 3.0 * Replace pytest-aiohttp with pytest-asyncio * Fix tests * More tests
1 parent 5013c49 commit 28f96b7

12 files changed

+144
-109
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,6 @@ ENV/
8787

8888
# Rope project settings
8989
.ropeproject
90+
91+
.mypy_cache
92+
.pytest_cache

.travis.yml

+2-6
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@ install:
99
- pip install codecov
1010

1111
script:
12-
- pytest tests
13-
- python setup.py check -rm
14-
- if python -c "import sys; sys.exit(sys.version_info < (3,5))"; then
15-
python setup.py check -s;
16-
fi
12+
- make test
1713

1814

1915
after_success:
@@ -29,4 +25,4 @@ deploy:
2925
on:
3026
tags: true
3127
all_branches: true
32-
python: 3.5
28+
python: 3.6

CHANGES.rst

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
CHANGES
22
=======
33

4+
3.0.0 (2018-05-05)
5+
------------------
6+
7+
- Drop Python 3.4, the minimal supported version is Python 3.5.3
8+
9+
- Provide type annotations
10+
411
2.0.1 (2018-03-13)
512
------------------
613

Makefile

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
test: mypy check
2+
pytest tests
3+
4+
5+
mypy:
6+
mypy async_timeout tests
7+
8+
9+
check:
10+
python setup.py check -rms

async_timeout/__init__.py

+32-21
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import asyncio
22
import sys
33

4+
from types import TracebackType
5+
from typing import Optional, Type
46

5-
__version__ = '2.0.1'
7+
8+
__version__ = '3.0.0'
69

710
PY_37 = sys.version_info >= (3, 7)
811

@@ -21,42 +24,48 @@ class timeout:
2124
timeout - value in seconds or None to disable timeout logic
2225
loop - asyncio compatible event loop
2326
"""
24-
def __init__(self, timeout, *, loop=None):
27+
def __init__(self, timeout: Optional[float],
28+
*, loop: asyncio.AbstractEventLoop=None) -> None:
2529
self._timeout = timeout
2630
if loop is None:
2731
loop = asyncio.get_event_loop()
2832
self._loop = loop
29-
self._task = None
33+
self._task = None # type: Optional[asyncio.Task]
3034
self._cancelled = False
31-
self._cancel_handler = None
32-
self._cancel_at = None
35+
self._cancel_handler = None # type: Optional[asyncio.Handle]
36+
self._cancel_at = None # type: Optional[float]
3337

34-
def __enter__(self):
38+
def __enter__(self) -> 'timeout':
3539
return self._do_enter()
3640

37-
def __exit__(self, exc_type, exc_val, exc_tb):
41+
def __exit__(self,
42+
exc_type: Type[BaseException],
43+
exc_val: BaseException,
44+
exc_tb: TracebackType) -> Optional[bool]:
3845
self._do_exit(exc_type)
46+
return None
3947

40-
@asyncio.coroutine
41-
def __aenter__(self):
48+
async def __aenter__(self) -> 'timeout':
4249
return self._do_enter()
4350

44-
@asyncio.coroutine
45-
def __aexit__(self, exc_type, exc_val, exc_tb):
51+
async def __aexit__(self,
52+
exc_type: Type[BaseException],
53+
exc_val: BaseException,
54+
exc_tb: TracebackType) -> None:
4655
self._do_exit(exc_type)
4756

4857
@property
49-
def expired(self):
58+
def expired(self) -> bool:
5059
return self._cancelled
5160

5261
@property
53-
def remaining(self):
62+
def remaining(self) -> Optional[float]:
5463
if self._cancel_at is not None:
5564
return max(self._cancel_at - self._loop.time(), 0.0)
5665
else:
5766
return None
5867

59-
def _do_enter(self):
68+
def _do_enter(self) -> 'timeout':
6069
# Support Tornado 5- without timeout
6170
# Details: https://github.com/python/asyncio/issues/392
6271
if self._timeout is None:
@@ -76,7 +85,7 @@ def _do_enter(self):
7685
self._cancel_at, self._cancel_task)
7786
return self
7887

79-
def _do_exit(self, exc_type):
88+
def _do_exit(self, exc_type: Type[BaseException]) -> None:
8089
if exc_type is asyncio.CancelledError and self._cancelled:
8190
self._cancel_handler = None
8291
self._task = None
@@ -85,20 +94,22 @@ def _do_exit(self, exc_type):
8594
self._cancel_handler.cancel()
8695
self._cancel_handler = None
8796
self._task = None
97+
return None
8898

89-
def _cancel_task(self):
90-
self._task.cancel()
91-
self._cancelled = True
99+
def _cancel_task(self) -> None:
100+
if self._task is not None:
101+
self._task.cancel()
102+
self._cancelled = True
92103

93104

94-
def current_task(loop):
105+
def current_task(loop: asyncio.AbstractEventLoop) -> asyncio.Task:
95106
if PY_37:
96-
task = asyncio.current_task(loop=loop)
107+
task = asyncio.current_task(loop=loop) # type: ignore
97108
else:
98109
task = asyncio.Task.current_task(loop=loop)
99110
if task is None:
100111
# this should be removed, tokio must use register_task and family API
101112
if hasattr(loop, 'current_task'):
102-
task = loop.current_task()
113+
task = loop.current_task() # type: ignore
103114

104115
return task

async_timeout/py.typed

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Placeholder

requirements.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pytest==3.5.0
2-
pytest-aiohttp==0.3.0
2+
pytest-asyncio==0.8.0
33
pytest-cov==2.5.1
44
docutils==0.14
5+
mypy==0.600
56
-e .

setup.cfg

+6
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
[tool:pytest]
22
addopts= --cov=async_timeout --cov-report=term --cov-report=html --cov-branch
3+
4+
[metadata]
5+
license_file = LICENSE
6+
7+
[mypy-pytest]
8+
ignore_missing_imports = true

setup.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import pathlib
22
import re
3+
import sys
34

45
from setuptools import setup
56

@@ -29,7 +30,6 @@ def read(name):
2930
'Intended Audience :: Developers',
3031
'Programming Language :: Python',
3132
'Programming Language :: Python :: 3',
32-
'Programming Language :: Python :: 3.4',
3333
'Programming Language :: Python :: 3.5',
3434
'Programming Language :: Python :: 3.6',
3535
'Topic :: Internet :: WWW/HTTP',
@@ -40,4 +40,5 @@ def read(name):
4040
url='https://github.com/aio-libs/async_timeout/',
4141
license='Apache 2',
4242
packages=['async_timeout'],
43-
include_package_data=False)
43+
python_requires='>=3.5.3',
44+
include_package_data=True)

tests/conftest.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import sys
1+
import pytest
22

33

4-
def pytest_ignore_collect(path, config):
5-
if 'py35' in str(path):
6-
if sys.version_info < (3, 5, 0):
7-
return True
4+
@pytest.fixture
5+
def loop(event_loop):
6+
return event_loop

tests/test_py35.py

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
from async_timeout import timeout
66

7+
pytestmark = pytest.mark.asyncio
8+
79

810
async def test_async_timeout(loop):
911
with pytest.raises(asyncio.TimeoutError):

0 commit comments

Comments
 (0)