-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
272 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
type: sphinx | ||
|
||
build: | ||
image: latest | ||
|
||
python: | ||
version: "3.6" | ||
pip_install: true | ||
extra_requirements: [doc] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Minimal makefile for Sphinx documentation | ||
# | ||
|
||
# You can set these variables from the command line, and also | ||
# from the environment for the first two. | ||
SPHINXOPTS ?= | ||
SPHINXBUILD ?= sphinx-build | ||
SOURCEDIR = . | ||
BUILDDIR = _build | ||
|
||
# Put it first so that "make" without argument is like "make help". | ||
help: | ||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) | ||
|
||
.PHONY: help Makefile | ||
|
||
# Catch-all target: route all unknown targets to Sphinx using the new | ||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). | ||
%: Makefile | ||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
API reference | ||
============= | ||
|
||
.. module:: typeguard | ||
|
||
.. autofunction:: check_type | ||
|
||
.. autofunction:: check_argument_types | ||
|
||
.. autofunction:: check_return_type | ||
|
||
.. autodecorator:: typechecked | ||
|
||
.. autoclass:: TypeChecker | ||
|
||
.. autoexception:: TypeHintWarning | ||
|
||
.. autoexception:: TypeWarning | ||
|
||
.. autoclass:: ForwardRefPolicy | ||
:members: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#!/usr/bin/env python3 | ||
import pkg_resources | ||
|
||
extensions = [ | ||
'sphinx.ext.autodoc', | ||
'sphinx.ext.intersphinx', | ||
'sphinx_autodoc_typehints' | ||
] | ||
|
||
templates_path = ['_templates'] | ||
source_suffix = '.rst' | ||
master_doc = 'index' | ||
project = 'Typeguard' | ||
author = 'Alex Grönholm' | ||
copyright = '2015, ' + author | ||
|
||
v = pkg_resources.get_distribution('typeguard').parsed_version | ||
version = v.base_version | ||
release = v.public | ||
|
||
language = None | ||
|
||
exclude_patterns = ['_build'] | ||
pygments_style = 'sphinx' | ||
highlight_language = 'python3' | ||
todo_include_todos = False | ||
add_module_names = False | ||
|
||
html_theme = 'sphinx_rtd_theme' | ||
html_static_path = ['_static'] | ||
htmlhelp_basename = 'typeguarddoc' | ||
|
||
intersphinx_mapping = {'python': ('http://docs.python.org/3/', None)} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
Typeguard | ||
========= | ||
|
||
.. toctree:: | ||
:maxdepth: 2 | ||
:caption: Quick links: | ||
|
||
api | ||
versionhistory | ||
|
||
Using type checker functions | ||
---------------------------- | ||
|
||
Two functions are provided, potentially for use with the ``assert`` statement: | ||
|
||
* :func:`~typeguard.check_argument_types` | ||
* :func:`~typeguard.check_return_type` | ||
|
||
These can be used to implement fine grained type checking for select functions. | ||
If the function is called with incompatible types, or :func:`~typeguard.check_return_type` is used | ||
and the return value does not match the return type annotation, then a :exc:`TypeError` is raised. | ||
|
||
For example:: | ||
|
||
from typeguard import check_argument_types, check_return_value | ||
|
||
def some_function(a: int, b: float, c: str, *args: str) -> bool: | ||
assert check_argument_types() | ||
... | ||
assert check_return_value(retval) | ||
return retval | ||
|
||
When combined with the ``assert`` statement, these checks are automatically removed from the code | ||
by the compiler when Python is executed in optimized mode (by passing the ``-O`` switch to the | ||
interpreter, or by setting the ``PYTHONOPTIMIZE`` environment variable to ``1`` (or higher). | ||
|
||
.. note:: This method is not reliable when used in nested functions (i.e. functions defined inside | ||
other functions). This is because this operating mode relies on finding the correct function | ||
object using the garbage collector, and when a nested function is running, its function object | ||
may no longer be around anymore, as it is only bound to the closure of the enclosing function. | ||
For this reason, it is recommended to use ``@typechecked`` instead for nested functions. | ||
|
||
Using the decorator | ||
------------------- | ||
|
||
The simplest way to type checking of both argument values and the return value for a single | ||
function is to use the ``@typechecked`` decorator:: | ||
|
||
from typeguard import typechecked | ||
|
||
@typechecked | ||
def some_function(a: int, b: float, c: str, *args: str) -> bool: | ||
... | ||
return retval | ||
|
||
@typechecked | ||
class SomeClass: | ||
# All type annotated methods (including static and class methods) are type checked. | ||
# Does not apply to inner classes! | ||
def method(x: int) -> int: | ||
... | ||
|
||
The decorator works just like the two previously mentioned checker functions except that it has no | ||
issues with nested functions. The drawback, however, is that it adds one stack frame per wrapped | ||
function which may make debugging harder. | ||
|
||
When a generator function is wrapped with ``@typechecked``, the yields, sends and the return value | ||
are also type checked against the :class:`~typing.Generator` annotation. The same applies to the | ||
yields and sends of an async generator (annotated with :class:`~typing.AsyncGenerator`). | ||
|
||
.. note:: | ||
The decorator also respects the optimized mode setting so it does nothing when the interpreter | ||
is running in optimized mode. | ||
|
||
Using the profiler hook | ||
----------------------- | ||
|
||
This type checking approach requires no code changes, but does come with a number of drawbacks. | ||
It relies on setting a profiler hook in the interpreter which gets called every time a new Python | ||
stack frame is entered or exited. | ||
|
||
The easiest way to use this approach is to use a :class:`~typeguard.TypeChecker` as a context | ||
manager:: | ||
|
||
from warnings import filterwarnings | ||
|
||
from typeguard import TypeChecker, TypeWarning | ||
|
||
# Display all TypeWarnings, not just the first one | ||
filterwarnings('always', category=TypeWarning) | ||
|
||
# Run your entire application inside this context block | ||
with TypeChecker(['mypackage', 'otherpackage']): | ||
mypackage.run_app() | ||
|
||
Alternatively, manually start (and stop) the checker:: | ||
|
||
checker = TypeChecker(['mypackage', 'otherpackage']) | ||
checker.start() | ||
mypackage.start_app() | ||
|
||
The profiler hook approach has the following drawbacks: | ||
|
||
* Return values of ``None`` are not type checked, as they cannot be distinguished from exceptions | ||
being raised | ||
* The hook relies on finding the target function using the garbage collector which may make it | ||
miss some type violations, especially with nested functions | ||
* Generator yield types are checked, send types are not | ||
* Generator yields cannot be distinguished from returns | ||
* Async generators are not type checked at all | ||
|
||
.. hint:: Some other things you can do with :class:`~typeguard.TypeChecker`: | ||
|
||
* Display all warnings from the start with ``python -W always::typeguard.TypeWarning`` | ||
* Redirect them to logging using :func:`logging.captureWarnings` | ||
* Record warnings in your pytest test suite and fail test(s) if you get any | ||
(see the `pytest documentation`_ about that) | ||
|
||
.. _pytest documentation: http://doc.pytest.org/en/latest/warnings.html#assertwarnings | ||
|
||
Checking types directly | ||
----------------------- | ||
|
||
Typeguard can also be used as a beefed-up version of :func:`isinstance` that also supports checking | ||
against annotations in the :mod:`typing` module:: | ||
|
||
from typeguard import check_type | ||
|
||
# Raises TypeError if there's a problem | ||
check_type('variablename', [1234], List[int]) |
Oops, something went wrong.