Brief History aka Brief History aka PEP-484 PEP-484 Designed on top of PEP-3107 (Function Annotations) Created on September 2014 Became part of standard library in Python 3.5 Endorsed by Guido van Rossum
Typeshed Typeshed python/typeshed Provide stubs for standard library And some widely-used shared libraries Have stubs for Python 2 & Python 3 Curated by PSF
Introduction Introduction Static type checker for Python Static type checker for Python Works with Python 3 & Python 2 code Still experimental Still experimental Developed at Dropbox Again. Endorsed by Guido
Output Output env/bin/mypy project/ project/signals.py: note: In function "cache_api_urls": project/signals.py:25: error: Argument 2 to "api_url" has incompatible type "str"; expected "int"
Long Lines / Ugly Code Long Lines / Ugly Code Before Before async def retrieve_tweets(pool, count=50): ... A er A er async def retrieve_tweets( pool: Pool, count: int=50 ) -> Sequence[Mapping[str, Any]]: ...
Stubs Stubs Hard to maintain Hard to maintain Easy to get into situation, when implementation != stub Completely same problems as with tests & documentation
Incomplete Stubs Incomplete Stubs $ mypy -c '...' : note: In function "main": :6: error: "module" has no attribute "ensure_future" :7: error: "module" has no attribute "ensure_future" :9: error: "module" has no attribute "gather" :6: error: Name 'some_async_def' is not defined :7: error: Name 'some_other_async_def' is not defined
Incomplete Stubs Incomplete Stubs from lxml import etree def fetch_data(url: str) -> etree._Element: ... def use_data(): data = fetch_data(URL) for item in data.iterfind(...): # Will fail with "has no attribute" error ...
Solution to Solution to # noqa: F401 # noqa: F401 PEP-526 implements syntax for variable annotations. uniques: Set[int] = set() number: int # Works even without assignment class Schema(object): name: str data: Dict[str, str] = {} Included in Python 3.6 Included in Python 3.6
# type: ignore # type: ignore Sooner or later, but you'll need to use # type: ingore asyncio.gather(*tasks, loop=loop) # type: ignore for item in data.iterfind('...'): # type: ignore mypy is still experimental and you'll need to use # type: ignore a er yelling WTF !
enforce enforce RussBaz/enforce Runtime type checking Designed to use at tests or for data validation import enforce @enforce.runtime_validation def hello(name: str) -> str: return 'Hello, {0}!'.format(name) hello('world') hello(1) # Will fail with RuntimeTypeError