How to quickly find type-issues in your Python code with Pytype

re.

match() returns None when no match is found.

Indeed, in these cases match.

group(1) will throw an exception.

Let’s fix the bug, by having the function return None for an invalid email address:import redef GetUsername(email_address): match = re.

match(r'([^@]+)@example.

com', email_address) if match is None: return None return match.

group(1) # <– Here, match can't be NoneNow, when we re-run pytype, the error is gone.

Pytype infers that if the code after the if gets executed, match is guaranteed not to be None.

Example #2: Validation of type annotationsIn Python 3, you can type-annotate (PEP 484) your code to help type-checking tools and other developers understand your intention.

Pytype is able to alert when your type annotations have mistakes:import refrom typing import Matchdef GetEmailMatch(email) -> Match: return re.

match(r'([^@]+)@example.

com', email)Let’s use pytype to check this code snippet:% pytype example.

pyAnalyzing 1 sources with 0 dependenciesFile "/.

/example.

py", line 5, in GetEmailMatch: bad option in return type [bad-return-type] Expected: Match Actually returned: NonePytype is telling us that GetEmailMatch might return None, but we annotated its return type as Match.

To fix this, we can use the Optional type annotation from the typing module:import refrom typing import Match, Optionaldef GetEmailMatch(email) -> Optional[Match]: return re.

match(r'([^@]+)@example.

com', email)Optional means that the return value can be a Match object or None.

Example #3: Merging back inferred type informationTo help you adopt type annotations, Pytype can add them into the code for you.

Let’s look at this code snippet:import re def GetEmailMatch(email): return re.

match(r'([^@]+)@example.

com', email)def GetUsername(email_address): match = GetEmailMatch(email_address) if match is None: return None return match.

group(1)To add type annotations to this code, we first run pytype on the file.

pytype saves the inferred type information into a .

pyi file.

Then, we can run merge-pyi to merge the type annotations back into the code:% pytype email.

py% merge-pyi -i email.

py pytype_output/email.

pyiAnd voilà!import refrom typing import Matchfrom typing import Optionaldef GetEmailMatch(email) -> Optional[Match[str]]: return re.

match(r'([^@]+)@example.

com', email)def GetUsername(email_address) -> Optional[str]: match = GetEmailMatch(email_address) if match is None: return None return match.

group(1)The type annotations, including import statements, are now in the source file.

For more usage examples and installation instructions, please visit Pytype on GitHub.

Thanks for reading!.. More details

Leave a Reply