When I refactor code I often find myself tediously adding type annotations that are obvious from context: functions that don't return anything, boolean flags, etcetera. That's where autotyping comes in: it automatically adds those types and inserts the right annotations.
It is built as a LibCST codemod; see the LibCST documentation for more information on how to use codemods.
Here's how to use it:
pip install autotyping
- Make sure you have a
.libcst.codemod.yaml
with'autotyping'
in themodules
list. For an example, see the.libcst.codemod.yaml
in this repo. - Run
python -m libcst.tool codemod autotyping.AutotypeCommand /path/to/my/code
By default it does nothing; you have to add flags to make it do more transformations. The following are supported:
- Annotating return types:
--none-return
: add a-> None
return type to functions without any return, yield, or raise in their body--scalar-return
: add a return annotation to functions that only return literal bool, str, bytes, int, or float objects.
- Annotating parameter types:
--bool-param
: add a: bool
annotation to any function parameter with a default ofTrue
orFalse
--int-param
,--float-param
,--str-param
,--bytes-param
: add an annotation to any parameter for which the default is a literal int, float, str, or bytes object--annotate-optional foo:bar.Baz
: for any parameter of the formfoo=None
, addBaz
, imported frombar
, as the type. For example, use--annotate-optional uid:my_types.Uid
to annotate anyuid
in your codebase with aNone
default asOptional[my_types.Uid]
.--annotate-named-param foo:bar.Baz
: annotate any parameter with no default that is namedfoo
withbar.Baz
. For example, use--annotate-named-param uid:my_types.Uid
to annotate anyuid
parameter in your codebase with no default asmy_types.Uid
.--guess-common-names
: infer certain parameter types from their names based on common patterns in open-source Python code. For example, infer that averbose
parameter is of typebool
.
- Annotating magical methods:
--annotate-magics
: add type annotation to certain magic methods. Currently this does the following:__str__
returnsstr
__repr__
returnsstr
__len__
returnsint
__length_hint__
returnsint
__init__
returnsNone
__del__
returnsNone
__bool__
returnsbool
__bytes__
returnsbytes
__format__
returnsstr
__contains__
returnsbool
__complex__
returnscomplex
__int__
returnsint
__float__
returnsfloat
__index__
returnsint
__exit__
: the three parameters areOptional[Type[BaseException]]
,Optional[BaseException]
, andOptional[TracebackType]
__aexit__
: same as__exit__
--annotate-imprecise-magics
: add imprecise type annotations for some additional magic methods. Currently this addstyping.Iterator
return annotations to__iter__
,__await__
, and__reversed__
. These annotations should have a generic parameter to indicate what you're iterating over, but that's too hard for autotyping to figure out.
- External integrations
--pyanalyze-report
: takes types suggested by pyanalyze'ssuggested_parameter_type
andsuggested_return_type
codes and applies them.--only-without-imports
: only apply pyanalyze suggestions that do not require new imports. This is useful because suggestions that require imports may need more manual work.
There are two shortcut flags to enable multiple transformations at once:
--safe
enables changes that should always be safe. This includes--none-return
,--scalar-return
, and--annotate-magics
.--aggressive
enables riskier changes that are more likely to produce new type checker errors. It includes all of--safe
as well as--bool-param
,--int-param
,--float-param
,--str-param
,--bytes-param
, and--annotate-imprecise-magics
.
Autotyping is intended to be a simple tool that uses heuristics to find annotations that would be tedious to add by hand. The heuristics may fail, and after you run autotyping you should run a type checker to verify that the types it added are correct.
Known limitations:
- autotyping does not model code flow through a function, so it may miss
implicit
None
returns
- Add
--guess-common-names
(contributed by John Litborn) - Fix the
--safe
and--aggressive
flags so they don't take ignored arguments --length-hint
should returnint
(contributed by Nikita Sobolev)- Fix bug in import adding (contributed by Shantanu)
- Add
--safe
and--aggressive
- Add
--pyanalyze-report
- Do not add
None
return types to methods marked with@abstractmethod
and to methods in stub files - Improve type inference:
"string" % ...
is alwaysstr
b"bytes" % ...
is alwaysbytes
- An
and
oror
operator where left and right sides are of the same type returns that type is
,is not
,in
, andnot in
always returnbool
- Initial PyPI release