Skip to content

Typing #37

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 4 commits into from
May 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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