ctags-lang-python¶
Random notes about tagging python source code with Universal Ctags
Version: | 6.0.0 |
---|---|
Manual group: | Universal Ctags |
Manual section: | 7 |
SYNOPSIS¶
DESCRIPTION¶
This man page gathers random notes about tagging python source code.
TAGGING import
STATEMENTS¶
Summary¶
import X
name kind role other noticeable fields X module imported N/A
import X as Y
name kind role other noticeable fields X module indirectlyImported N/A Y namespace definition nameref:module:X
from X import *
name kind role other noticeable fields X module namespace N/A
from X import Y
name kind role other noticeable fields X module namespace N/A Y unknown imported scope:module:X
from X import Y as Z
name kind role other noticeable fields X module namespace N/A Y unknown indirectlyImported scope:module:X Z unknown definition nameref:unknown:Y
Examples¶
“input.py”
import X0
“output.tags” with “--options=NONE -o - --extras=+r --fields=+rzK input.py”
A tag for an imported module has module
kind with imported
role. The
module is not defined here; it is defined in another file. So the tag for the
imported module is a reference tag; specify --extras=+r
(or
--extras=+{reference}
) option for tagging it. “roles:” field enabled with
--fields=+r
is for recording the module is “imported” to the tag file.
“input.py”
import X1 as Y1
“output.tags” with “--options=NONE -o - --extras=+r --fields=+rzK --fields-Python=+{nameref} input.py”
“Y1” introduces a new name and is defined here. So “Y1” is tagged as a
definition tag. “X1” is imported in a way that its name cannot be used
in this source file. For letting client tools know that the name cannot be used,
indirectlyImported
role is assigned for “X1”. “Y1” is the name for
accessing objects defined in the module imported via “X1”. For recording this
relationship, nameref:
field is attached to the tag of “Y1”. Instead of
module
kind, namespace
kind is assigned to “Y1” because “Y1” itself
isn’t a module.
“input.py”
from X2 import *
“output.tags” with “--options=NONE -o - --extras=+r --fields=+rzK input.py”
The module is not defined here; it is defined in another file. So the tag for
the imported module is a reference tag. Unlike “X0” in “import X0”, “X2” may not
be used because the names defined in “X2” can be used in this source file. To represent
the difference namespace
role is attached to “X2” instead of imported
.
“input.py”
from X3 import Y3
“output.tags” with “--options=NONE -o - --extras=+r --fields=+rzKZ input.py”
“Y3” is a name for a language object defined in “X3” module. “scope:module:X3”
attached to “Y3” represents this relation between “Y3” and “X3”. ctags
assigns unknown
kind to “Y3” because ctags cannot know whether “Y3” is a
class, a variable, or a function from the input file.
“input.py”
from X4 import Y4 as Z4
“output.tags” with “--options=NONE -o - --extras=+r --fields=+rzKZ input.py”
“Y4” is similar to “Y3” of “from X3 import Y3” but the name cannot be used here.
indirectlyImported
role assigned to “Y4” representing this. “Z4” is the name for
accessing the language object named in “Y4” in “X4” module. “nameref:unknown:Y4”
attached to “Z4” and “scope:module:X4” attached to “Y4” represent the relations.
LAMBDA EXPRESSION AND TYPE HINT¶
Summary¶
id = lambda var0: var0
name kind role other noticeable fields id function definition signature:(var0)
id_t: Callable[[int], int] = lambda var1: var1
name kind role other noticeable fields id_t variable definition typeref:typename:Callable[[int], int] nameref:function:anonFuncN anonFuncN function definition signature:(var1)
Examples¶
“input.py”
from typing import Callable
id = lambda var0: var0
id_t: Callable[[int], int] = lambda var1: var1
“output.tags” with “--options=NONE -o - --sort=no --fields=+KS --fields-Python=+{nameref} --extras=+{anonymous} input.py”
If a variable (“id”) with no type hint is initialized with a lambda expression,
ctags assigns function
kind for the tag of “id”.
If a variable (“id_t”) with a type hint is initialized with a lambda expression,
ctags assigns variable
kind for the tag of “id_t” with typeref:
and
nameref:
fields. ctags fills typeref:
field with the value of the type
hint. The way of filling nameref:
is a bit complicated.
For the lambda expression used in initializing the type-hint’ed variable, ctags
creates anonymous
extra tag (“anonFunc84011d2c0101”). ctags fills the
nameref:
field of “id_t” with the name of anonymous
extra tag:
“nameref:function:anonFunc84011d2c0101”.
You may think why ctags does so complicated, and why ctags doesn’t emit following tags output for the input:
id input.py /^id = \\$/;" function signature:(var0)
id_t input.py /^id_t: \\$/;" function typeref:typename:Callable[[int], int] signature:(var1)
There is a reason. The other languages of ctags obey the following rule: ctags fills
typeref:
field for a tag of a callable object (like function) with the type
of its return value. If we consider “id_t” is a function, its typeref:
field
should have “typename:int”. However, for filling typeref:
with “typename:int”,
ctags has to analyze “Callable[[int], int]” deeper. We don’t want to do so.