Skip to content

Commit 4187397

Browse files
committed
Support Python 3.6+
1 parent 16e6bfb commit 4187397

File tree

12 files changed

+53
-138
lines changed

12 files changed

+53
-138
lines changed

docs/source/conf.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#!/usr/bin/env python3
2-
# -*- coding: utf-8 -*-
32
#
43
# Documentation build configuration file, created by
54
# sphinx-quickstart on Sat Jan 21 19:11:14 2017.

setup.py

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,13 @@
1-
# coding: utf-8
2-
from __future__ import absolute_import, division, print_function
3-
4-
from io import open
5-
61
from setuptools import find_packages, setup
72

83
version = dict()
94

10-
# read _version.py as bytes, otherwise exec will complain about
11-
# 'coding: utf-8', which we want there for the normal Python 2 import
12-
with open('src/outcome/_version.py', 'rb') as fp:
5+
with open('src/outcome/_version.py') as fp:
136
version_mod = fp.read()
147

158
exec(version_mod, version)
169

17-
LONG_DESC = open('README.rst', encoding='utf-8').read()
10+
LONG_DESC = open('README.rst').read()
1811

1912
setup(
2013
name='outcome',
@@ -33,7 +26,7 @@
3326
packages=find_packages('src'),
3427
package_dir={'': 'src'},
3528
install_requires=['attrs>=19.2.0'],
36-
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
29+
python_requires='>=3.6',
3730
keywords='result',
3831
classifiers=[
3932
'Development Status :: 5 - Production/Stable',
@@ -44,10 +37,9 @@
4437
'Operating System :: POSIX :: Linux',
4538
'Operating System :: MacOS :: MacOS X',
4639
'Operating System :: Microsoft :: Windows',
47-
'Programming Language :: Python :: 2.7',
48-
'Programming Language :: Python :: 3.4',
49-
'Programming Language :: Python :: 3.5',
5040
'Programming Language :: Python :: 3.6',
41+
'Programming Language :: Python :: 3.7',
42+
'Programming Language :: Python :: 3.8',
5143
'Programming Language :: Python :: Implementation :: CPython',
5244
'Programming Language :: Python :: Implementation :: PyPy',
5345
],

src/outcome/__init__.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,12 @@
1-
# coding: utf-8
21
"""Top-level package for outcome."""
3-
from __future__ import absolute_import, division, print_function
4-
5-
import sys
62

3+
from ._impl import Error, Outcome, Value, acapture, capture
74
from ._util import AlreadyUsedError, fixup_module_metadata
85
from ._version import __version__
96

10-
if sys.version_info >= (3, 5):
11-
from ._async import Error, Outcome, Value, acapture, capture
12-
__all__ = (
13-
'Error', 'Outcome', 'Value', 'acapture', 'capture', 'AlreadyUsedError'
14-
)
15-
else:
16-
from ._sync import Error, Outcome, Value, capture
17-
__all__ = ('Error', 'Outcome', 'Value', 'capture', 'AlreadyUsedError')
7+
__all__ = (
8+
'Error', 'Outcome', 'Value', 'acapture', 'capture', 'AlreadyUsedError'
9+
)
1810

1911
fixup_module_metadata(__name__, globals())
2012
del fixup_module_metadata

src/outcome/_async.py

Lines changed: 0 additions & 68 deletions
This file was deleted.

src/outcome/_sync.py renamed to src/outcome/_impl.py

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
# coding: utf-8
2-
from __future__ import absolute_import, division, print_function
3-
41
import abc
52

63
import attr
74

8-
from ._util import ABC, AlreadyUsedError, remove_tb_frames
5+
from ._util import AlreadyUsedError, remove_tb_frames
96

10-
__all__ = ['Error', 'Outcome', 'Value', 'capture']
7+
__all__ = ['Error', 'Outcome', 'Value', 'acapture', 'capture']
118

129

1310
def capture(sync_fn, *args, **kwargs):
@@ -17,15 +14,30 @@ def capture(sync_fn, *args, **kwargs):
1714
Either a :class:`Value` or :class:`Error` as appropriate.
1815
1916
"""
17+
# _sync.capture references ErrorBase and ValueBase
2018
try:
2119
return Value(sync_fn(*args, **kwargs))
2220
except BaseException as exc:
2321
exc = remove_tb_frames(exc, 1)
2422
return Error(exc)
2523

2624

25+
async def acapture(async_fn, *args, **kwargs):
26+
"""Run ``await async_fn(*args, **kwargs)`` and capture the result.
27+
28+
Returns:
29+
Either a :class:`Value` or :class:`Error` as appropriate.
30+
31+
"""
32+
try:
33+
return Value(await async_fn(*args, **kwargs))
34+
except BaseException as exc:
35+
exc = remove_tb_frames(exc, 1)
36+
return Error(exc)
37+
38+
2739
@attr.s(repr=False, init=False, slots=True)
28-
class Outcome(ABC):
40+
class Outcome(abc.ABC):
2941
"""An abstract class representing the result of a Python computation.
3042
3143
This class has two concrete subclasses: :class:`Value` representing a
@@ -69,6 +81,17 @@ def send(self, gen):
6981
7082
"""
7183

84+
@abc.abstractmethod
85+
async def asend(self, agen):
86+
"""Send or throw the contained value or exception into the given async
87+
generator object.
88+
89+
Args:
90+
agen: An async generator object supporting ``.asend()`` and
91+
``.athrow()`` methods.
92+
93+
"""
94+
7295

7396
@attr.s(frozen=True, repr=False, slots=True)
7497
class Value(Outcome):
@@ -80,7 +103,7 @@ class Value(Outcome):
80103
"""The contained value."""
81104

82105
def __repr__(self):
83-
return 'Value({!r})'.format(self.value)
106+
return f'Value({self.value!r})'
84107

85108
def unwrap(self):
86109
self._set_unwrapped()
@@ -90,6 +113,10 @@ def send(self, gen):
90113
self._set_unwrapped()
91114
return gen.send(self.value)
92115

116+
async def asend(self, agen):
117+
self._set_unwrapped()
118+
return await agen.asend(self.value)
119+
93120

94121
@attr.s(frozen=True, repr=False, slots=True)
95122
class Error(Outcome):
@@ -101,7 +128,7 @@ class Error(Outcome):
101128
"""The contained exception object."""
102129

103130
def __repr__(self):
104-
return 'Error({!r})'.format(self.error)
131+
return f'Error({self.error!r})'
105132

106133
def unwrap(self):
107134
self._set_unwrapped()
@@ -113,3 +140,7 @@ def unwrap(self):
113140
def send(self, it):
114141
self._set_unwrapped()
115142
return it.throw(self.error)
143+
144+
async def asend(self, agen):
145+
self._set_unwrapped()
146+
return await agen.athrow(self.error)

src/outcome/_util.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
# coding: utf-8
2-
from __future__ import absolute_import, division, print_function
3-
4-
import abc
51
import sys
62

73

@@ -25,17 +21,7 @@ def fix_one(obj):
2521

2622

2723
def remove_tb_frames(exc, n):
28-
if sys.version_info < (3,):
29-
return exc
3024
tb = exc.__traceback__
3125
for _ in range(n):
3226
tb = tb.tb_next
3327
return exc.with_traceback(tb)
34-
35-
36-
if sys.version_info < (3,):
37-
38-
class ABC(object):
39-
__metaclass__ = abc.ABCMeta
40-
else:
41-
ABC = abc.ABC

src/outcome/_version.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# coding: utf-8
21
# This file is imported from __init__.py and exec'd from setup.py
32

43
__version__ = "1.0.1"

test-requirements.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
pytest
22
pytest-cov
3-
pytest-asyncio; python_version >= '3.5'
4-
async-generator; python_version >= '3.5'
3+
pytest-asyncio

tests/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +0,0 @@
1-
# coding: utf-8
2-
from __future__ import absolute_import, division, print_function

tests/conftest.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
# coding: utf-8
2-
from __future__ import absolute_import, division, print_function
3-
41
import sys
52

63
import pytest

0 commit comments

Comments
 (0)