Skip to content

Commit

Permalink
Typing (#37)
Browse files Browse the repository at this point in the history
* Bump to 3.0

* Replace pytest-aiohttp with pytest-asyncio

* Fix tests

* More tests
  • Loading branch information
asvetlov authored May 5, 2018
1 parent 5013c49 commit 28f96b7
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 109 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,6 @@ ENV/

# Rope project settings
.ropeproject

.mypy_cache
.pytest_cache
8 changes: 2 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@ install:
- pip install codecov

script:
- pytest tests
- python setup.py check -rm
- if python -c "import sys; sys.exit(sys.version_info < (3,5))"; then
python setup.py check -s;
fi
- make test


after_success:
Expand All @@ -29,4 +25,4 @@ deploy:
on:
tags: true
all_branches: true
python: 3.5
python: 3.6
7 changes: 7 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
CHANGES
=======

3.0.0 (2018-05-05)
------------------

- Drop Python 3.4, the minimal supported version is Python 3.5.3

- Provide type annotations

2.0.1 (2018-03-13)
------------------

Expand Down
10 changes: 10 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
test: mypy check
pytest tests


mypy:
mypy async_timeout tests


check:
python setup.py check -rms
53 changes: 32 additions & 21 deletions async_timeout/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import asyncio
import sys

from types import TracebackType
from typing import Optional, Type

__version__ = '2.0.1'

__version__ = '3.0.0'

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

Expand All @@ -21,42 +24,48 @@ class timeout:
timeout - value in seconds or None to disable timeout logic
loop - asyncio compatible event loop
"""
def __init__(self, timeout, *, loop=None):
def __init__(self, timeout: Optional[float],
*, loop: asyncio.AbstractEventLoop=None) -> None:
self._timeout = timeout
if loop is None:
loop = asyncio.get_event_loop()
self._loop = loop
self._task = None
self._task = None # type: Optional[asyncio.Task]
self._cancelled = False
self._cancel_handler = None
self._cancel_at = None
self._cancel_handler = None # type: Optional[asyncio.Handle]
self._cancel_at = None # type: Optional[float]

def __enter__(self):
def __enter__(self) -> 'timeout':
return self._do_enter()

def __exit__(self, exc_type, exc_val, exc_tb):
def __exit__(self,
exc_type: Type[BaseException],
exc_val: BaseException,
exc_tb: TracebackType) -> Optional[bool]:
self._do_exit(exc_type)
return None

@asyncio.coroutine
def __aenter__(self):
async def __aenter__(self) -> 'timeout':
return self._do_enter()

@asyncio.coroutine
def __aexit__(self, exc_type, exc_val, exc_tb):
async def __aexit__(self,
exc_type: Type[BaseException],
exc_val: BaseException,
exc_tb: TracebackType) -> None:
self._do_exit(exc_type)

@property
def expired(self):
def expired(self) -> bool:
return self._cancelled

@property
def remaining(self):
def remaining(self) -> Optional[float]:
if self._cancel_at is not None:
return max(self._cancel_at - self._loop.time(), 0.0)
else:
return None

def _do_enter(self):
def _do_enter(self) -> 'timeout':
# Support Tornado 5- without timeout
# Details: https://github.com/python/asyncio/issues/392
if self._timeout is None:
Expand All @@ -76,7 +85,7 @@ def _do_enter(self):
self._cancel_at, self._cancel_task)
return self

def _do_exit(self, exc_type):
def _do_exit(self, exc_type: Type[BaseException]) -> None:
if exc_type is asyncio.CancelledError and self._cancelled:
self._cancel_handler = None
self._task = None
Expand All @@ -85,20 +94,22 @@ def _do_exit(self, exc_type):
self._cancel_handler.cancel()
self._cancel_handler = None
self._task = None
return None

def _cancel_task(self):
self._task.cancel()
self._cancelled = True
def _cancel_task(self) -> None:
if self._task is not None:
self._task.cancel()
self._cancelled = True


def current_task(loop):
def current_task(loop: asyncio.AbstractEventLoop) -> asyncio.Task:
if PY_37:
task = asyncio.current_task(loop=loop)
task = asyncio.current_task(loop=loop) # type: ignore
else:
task = asyncio.Task.current_task(loop=loop)
if task is None:
# this should be removed, tokio must use register_task and family API
if hasattr(loop, 'current_task'):
task = loop.current_task()
task = loop.current_task() # type: ignore

return task
1 change: 1 addition & 0 deletions async_timeout/py.typed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Placeholder
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pytest==3.5.0
pytest-aiohttp==0.3.0
pytest-asyncio==0.8.0
pytest-cov==2.5.1
docutils==0.14
mypy==0.600
-e .
6 changes: 6 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
[tool:pytest]
addopts= --cov=async_timeout --cov-report=term --cov-report=html --cov-branch

[metadata]
license_file = LICENSE

[mypy-pytest]
ignore_missing_imports = true
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pathlib
import re
import sys

from setuptools import setup

Expand Down Expand Up @@ -29,7 +30,6 @@ def read(name):
'Intended Audience :: Developers',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Topic :: Internet :: WWW/HTTP',
Expand All @@ -40,4 +40,5 @@ def read(name):
url='https://github.com/aio-libs/async_timeout/',
license='Apache 2',
packages=['async_timeout'],
include_package_data=False)
python_requires='>=3.5.3',
include_package_data=True)
9 changes: 4 additions & 5 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import sys
import pytest


def pytest_ignore_collect(path, config):
if 'py35' in str(path):
if sys.version_info < (3, 5, 0):
return True
@pytest.fixture
def loop(event_loop):
return event_loop
2 changes: 2 additions & 0 deletions tests/test_py35.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

from async_timeout import timeout

pytestmark = pytest.mark.asyncio


async def test_async_timeout(loop):
with pytest.raises(asyncio.TimeoutError):
Expand Down
Loading

0 comments on commit 28f96b7

Please sign in to comment.