Skip to content

Commit a6144a1

Browse files
Merge pull request #36 from TeamSpen210/typing
Add type hints
2 parents 65ab938 + e78527c commit a6144a1

File tree

16 files changed

+439
-53
lines changed

16 files changed

+439
-53
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ htmlcov/
3939
.coverage.*
4040
.cache
4141
.pytest_cache
42+
.mypy_cache
4243
nosetests.xml
4344
coverage.xml
4445

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
include README.rst CHEATSHEET.rst LICENSE* CODE_OF_CONDUCT* CONTRIBUTING*
22
include .coveragerc .style.yapf
33
include test-requirements.txt
4+
include src/outcome/py.typed
45
recursive-include docs *
56
prune docs/build
67
recursive-include tests *.py

ci.sh

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@ pip install -U pip setuptools wheel
99
python setup.py sdist --formats=zip
1010
pip install dist/*.zip
1111

12+
# Install dependencies.
13+
pip install -Ur test-requirements.txt
14+
1215
if [ "$CHECK_FORMATTING" = "1" ]; then
13-
pip install yapf==${YAPF_VERSION} isort>=5
16+
pip install yapf==${YAPF_VERSION} isort>=5 mypy pyright
1417
if ! yapf -rpd setup.py src tests; then
1518
cat <<EOF
1619
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -29,9 +32,6 @@ EOF
2932
exit 1
3033
fi
3134

32-
# required for isort to order test imports correctly
33-
pip install -Ur test-requirements.txt
34-
3535
if ! isort --check-only --diff . ; then
3636
cat <<EOF
3737
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -49,12 +49,46 @@ in your local checkout.
4949
EOF
5050
exit 1
5151
fi
52+
53+
if ! mypy src/ tests/type_tests.py ; then
54+
cat <<EOF
55+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
56+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
57+
58+
Type checking errors were found (listed above). To get more detail, run
59+
60+
pip install mypy
61+
mypy src/ tests/type_tests.py
62+
63+
in your local checkout.
64+
65+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
66+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
67+
EOF
68+
exit 1
69+
fi
70+
71+
if ! pyright --verifytypes outcome src/outcome/ ; then
72+
cat <<EOF
73+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
74+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
75+
76+
Types are not complete (listed above). To get more detail, run
77+
78+
pip install pyright
79+
pyright --verifytypes outcome src/outcome/
80+
81+
in your local checkout.
82+
83+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
84+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
85+
EOF
86+
exit 1
87+
fi
88+
5289
exit 0
5390
fi
5491

55-
# Actual tests
56-
pip install -Ur test-requirements.txt
57-
5892
pytest -W error -ra -v tests --cov --cov-config=.coveragerc
5993

6094
bash <(curl -s https://codecov.io/bash)

ci/rtd-requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# RTD is currently installing 1.5.3, which has a bug in :lineno-match:
2-
sphinx >= 1.6.1
2+
sphinx >= 4.0, < 6.2
33
sphinx_rtd_theme
44
sphinxcontrib-trio

docs/source/api.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@ API Reference
1414
:members:
1515
:inherited-members:
1616

17+
.. py:data:: Maybe
18+
:value: Value[ResultT] | Error
19+
20+
A convenience alias to a union of both results. This allows type checkers to perform
21+
exhaustiveness checking when ``isinstance()`` is used with either class::
22+
23+
outcome: Maybe[int] = capture(some_function, 1, 2, 3)
24+
if isinstance(outcome, Value):
25+
# Type checkers know it's a Value[int] here.
26+
else:
27+
# It must be an Error.
28+
1729
.. autoclass:: Value
1830
:members:
1931
:inherited-members:

docs/source/conf.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#
1919
import os
2020
import sys
21+
2122
# So autodoc can import our package
2223
sys.path.insert(0, os.path.abspath('../..'))
2324

@@ -27,6 +28,13 @@
2728
nitpick_ignore = [
2829
# Format is ('sphinx reference type', 'string'), e.g.:
2930
('py:obj', 'bytes-like'),
31+
# Typevars aren't found, for some reason.
32+
('py:class', 'ArgsT'),
33+
('py:class', 'ArgsT.args'),
34+
('py:class', 'ArgsT.kwargs'),
35+
('py:class', 'ResultT'),
36+
('py:class', 'outcome._impl.ResultT'),
37+
('py:class', 'outcome._impl.ValueT'),
3038
]
3139

3240
# -- General configuration ------------------------------------------------
@@ -76,6 +84,7 @@
7684
#
7785
# The short X.Y version.
7886
import outcome
87+
7988
version = outcome.__version__
8089
# The full version, including alpha/beta/rc tags.
8190
release = version
@@ -101,7 +110,6 @@
101110
# If true, `todo` and `todoList` produce output, else they produce nothing.
102111
todo_include_todos = False
103112

104-
105113
# -- Options for HTML output ----------------------------------------------
106114

107115
# The theme to use for HTML and HTML Help pages. See the documentation for
@@ -113,6 +121,7 @@
113121
# testing, but also because if we don't then RTD will throw away our
114122
# html_theme_options.
115123
import sphinx_rtd_theme
124+
116125
html_theme = 'sphinx_rtd_theme'
117126
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
118127

@@ -135,13 +144,11 @@
135144
# so a file named 'default.css' will overwrite the builtin 'default.css'.
136145
html_static_path = ['_static']
137146

138-
139147
# -- Options for HTMLHelp output ------------------------------------------
140148

141149
# Output file base name for HTML help builder.
142150
htmlhelp_basename = 'outcomedoc'
143151

144-
145152
# -- Options for LaTeX output ---------------------------------------------
146153

147154
latex_elements = {
@@ -166,28 +173,23 @@
166173
# (source start file, target name, title,
167174
# author, documentclass [howto, manual, or own class]).
168175
latex_documents = [
169-
(master_doc, 'outcome.tex', 'Trio Documentation',
170-
author, 'manual'),
176+
(master_doc, 'outcome.tex', 'Trio Documentation', author, 'manual'),
171177
]
172178

173-
174179
# -- Options for manual page output ---------------------------------------
175180

176181
# One entry per manual page. List of tuples
177182
# (source start file, name, description, authors, manual section).
178-
man_pages = [
179-
(master_doc, 'outcome', 'outcome Documentation',
180-
[author], 1)
181-
]
182-
183+
man_pages = [(master_doc, 'outcome', 'outcome Documentation', [author], 1)]
183184

184185
# -- Options for Texinfo output -------------------------------------------
185186

186187
# Grouping the document tree into Texinfo files. List of tuples
187188
# (source start file, target name, title, author,
188189
# dir menu entry, description, category)
189190
texinfo_documents = [
190-
(master_doc, 'outcome', 'outcome Documentation',
191-
author, 'outcome', 'Capture the outcome of Python function call.',
192-
'Miscellaneous'),
191+
(
192+
master_doc, 'outcome', 'outcome Documentation', author, 'outcome',
193+
'Capture the outcome of Python function call.', 'Miscellaneous'
194+
),
193195
]

newsfragments/36.feature.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Added type hints to the package. :py:class:`Value` and :py:class`Outcome` are now generic.
2+
A type alias was also added (:py:data:`Maybe`) for the union of :py:class:`Value`
3+
and :py:class:`Error`.

pyproject.toml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,33 @@ filename = "docs/source/history.rst"
44
directory = "newsfragments"
55
underlines = ["-", "~", "^"]
66
issue_format = "`#{issue} <https://github.com/python-trio/outcome/issues/{issue}>`__"
7+
8+
[tool.isort]
9+
combine_as_imports = true
10+
profile = "black"
11+
skip_gitignore = true
12+
13+
[tool.mypy]
14+
# Be strict about use of Mypy
15+
strict = true
16+
warn_unused_ignores = true
17+
warn_unused_configs = true
18+
warn_redundant_casts = true
19+
warn_no_return = true
20+
warn_unreachable = true
21+
warn_return_any = true
22+
23+
# Avoid subtle backsliding
24+
disallow_incomplete_defs = true
25+
disallow_subclassing_any = true
26+
disallow_any_unimported = true
27+
disallow_any_generics = true
28+
disallow_any_explicit = false
29+
30+
check_untyped_defs = true
31+
disallow_untyped_calls = true
32+
disallow_untyped_defs = true
33+
disallow_untyped_decorators = true
34+
35+
# DO NOT use `ignore_errors`; it doesn't apply
36+
# downstream and users have to deal with them.

setup.cfg

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@ branch = True
1212
source =
1313
outcome
1414
tests/
15+
omit =
16+
tests/type_tests.py
1517

1618
[coverage:report]
1719
precision = 1
1820
exclude_lines =
1921
pragma: no cover
2022
abc.abstractmethod
23+
if TYPE_CHECKING:
24+
@overload
2125

2226
[tool:pytest]
2327
asyncio_mode = strict

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
license='MIT OR Apache-2.0',
2626
packages=find_packages('src'),
2727
package_dir={'': 'src'},
28+
include_package_data=True,
2829
install_requires=['attrs>=19.2.0'],
2930
python_requires='>=3.7',
3031
keywords='result',

0 commit comments

Comments
 (0)