Automatically add simple type annotations to your code
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.
Autotyping can be called directly from the CLI, be used as a pre-commit hook or run via the libcst
interface as a codemod.
Here's how to use it from the CLI:
pip install autotyping
python -m autotyping /path/to/my/code
By default it does nothing; you have to add flags to make it do more transformations. The following are supported:
--none-return
: add a -> None
return type to functions without any--scalar-return
: add a return annotation to functions that only return--bool-param
: add a : bool
annotation to any functionTrue
or False
--int-param
, --float-param
, --str-param
, --bytes-param
: add--annotate-optional foo:bar.Baz
: for any parameter of the formfoo=None
, add Baz
, imported from bar
, as the type. For example,--annotate-optional uid:my_types.Uid
to annotate any uid
in yourNone
default as Optional[my_types.Uid]
.--annotate-named-param foo:bar.Baz
: annotate any parameter with nofoo
with bar.Baz
. For example, use--annotate-named-param uid:my_types.Uid
to annotate any uid
my_types.Uid
.--guess-common-names
: infer certain parameter types from their namesverbose
parameter is of type bool
.--annotate-magics
: add type annotation to certain magic methods.__str__
returns str
__repr__
returns str
__len__
returns int
__length_hint__
returns int
__init__
returns None
__del__
returns None
__bool__
returns bool
__bytes__
returns bytes
__format__
returns str
__contains__
returns bool
__complex__
returns complex
__int__
returns int
__float__
returns float
__index__
returns int
__exit__
: the three parameters are Optional[Type[BaseException]]
,Optional[BaseException]
, and Optional[TracebackType]
__aexit__
: same as __exit__
--annotate-imprecise-magics
: add imprecise type annotations fortyping.Iterator
__iter__
, __await__
, and __reversed__
.--pyanalyze-report
: takes types suggested bysuggested_parameter_type
suggested_return_type
codes and applies them. You can generate thesepyanalyze --json-output failures.json -e suggested_return_type -e suggested_parameter_type -v .
--only-without-imports
: only apply pyanalyze suggestions that do not requireThere 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--safe
as well as --bool-param
,--int-param
, --float-param
, --str-param
, --bytes-param
, and--annotate-imprecise-magics
.Autotyping is built as a LibCST codemod; see the LibCST documentation for more information on how to use codemods.
If you wish to run things through the libcst.tool
interface, you can do this like so:
.libcst.codemod.yaml
with 'autotyping'
in the modules
list..libcst.codemod.yaml
in this repo.python -m libcst.tool codemod autotyping.AutotypeCommand /path/to/my/code
Pre-commit hooks are scripts that runs automatically before a commit is made, which makes them really handy for checking and enforcing code-formatting (or in this case, typing)
autotyping
as a pre-commit hook,pip install pre-commit
.pre-commit-config.yaml
file at the root- repos:
- repo: https://github.com/JelleZijlstra/autotyping
rev: 24.9.0
hooks:
- id: autotyping
stages: [commit]
types: [python]
args: [--safe] # or alternatively, --aggressive, or any of the other flags mentioned above
pre-commit install
Now whenever you commit changes, autotyping will automatically add type annotations to your code!
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:
None
returnspython3 -m autotyping
to invoke the tool. (Thanks to Shantanu Jain.)iterables
(contributed by--guess-common-names
(contributed by John Litborn)--safe
and --aggressive
flags so they don't take--length-hint
should return int
(contributed by Nikita Sobolev)--safe
and --aggressive
--pyanalyze-report
None
return types to methods marked with @abstractmethod
and"string" % ...
is always str
b"bytes" % ...
is always bytes
and
or or
operator where left and right sides are of the same typeis
, is not
, in
, and not in
always return bool