.\" Man page generated from reStructuredText. . .TH CTAGS-LANG-PYTHON 7 "" "5.9.0" "Universal Ctags" .SH NAME ctags-lang-python \- Random notes about tagging python source code with Universal Ctags . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .SH SYNOPSIS .nf \fBctags\fP ... \-\-languages=+Python ... \fBctags\fP ... \-\-language\-force=Python ... \fBctags\fP ... \-\-map\-Python=+.py ... .fi .sp .SH DESCRIPTION .sp This man page gathers random notes about tagging python source code. .SH TAGGING IMPORT STATEMENTS .SS Summary .sp \fIimport X\fP .INDENT 0.0 .INDENT 3.5 .TS center; |l|l|l|l|. _ T{ name T} T{ kind T} T{ role T} T{ other noticeable fields T} _ T{ X T} T{ module T} T{ imported T} T{ N/A T} _ .TE .UNINDENT .UNINDENT .sp \fIimport X as Y\fP .INDENT 0.0 .INDENT 3.5 .TS center; |l|l|l|l|. _ T{ name T} T{ kind T} T{ role T} T{ other noticeable fields T} _ T{ X T} T{ module T} T{ indirectlyImported T} T{ N/A T} _ T{ Y T} T{ namespace T} T{ definition T} T{ nameref:module:X T} _ .TE .UNINDENT .UNINDENT .sp \fIfrom X import *\fP .INDENT 0.0 .INDENT 3.5 .TS center; |l|l|l|l|. _ T{ name T} T{ kind T} T{ role T} T{ other noticeable fields T} _ T{ \fIX\fP T} T{ module T} T{ namespace T} T{ N/A T} _ .TE .UNINDENT .UNINDENT .sp \fIfrom X import Y\fP .INDENT 0.0 .INDENT 3.5 .TS center; |l|l|l|l|. _ T{ name T} T{ kind T} T{ role T} T{ other noticeable fields T} _ T{ \fIX\fP T} T{ module T} T{ namespace T} T{ N/A T} _ T{ \fIY\fP T} T{ unknown T} T{ imported T} T{ scope:module:\fIX\fP T} _ .TE .UNINDENT .UNINDENT .sp \fIfrom X import Y as Z\fP .INDENT 0.0 .INDENT 3.5 .TS center; |l|l|l|l|. _ T{ name T} T{ kind T} T{ role T} T{ other noticeable fields T} _ T{ \fIX\fP T} T{ module T} T{ namespace T} T{ N/A T} _ T{ \fIY\fP T} T{ unknown T} T{ indirectlyImported T} T{ scope:module:\fIX\fP T} _ T{ \fIZ\fP T} T{ unknown T} T{ definition T} T{ nameref:unknown:\fIY\fP T} _ .TE .UNINDENT .UNINDENT .\" ===================== ==== ========== ================== =================== .\" input code name kind role other noticeable fields .\" ===================== ==== ========== ================== =================== .\" import X X module imported .\" import X as Y X module indirectlyImported .\" import X as Y Y namespace definition nameref:module:X .\" from X import * X module namespace .\" from X import Y X module namespace .\" from X import Y Y unknown imported scope:module:X .\" from X import Y as Z X module namespace .\" from X import Y as Z Y unknown indirectlyImported scope:module:X .\" from X import Y as Z Z unknown definition nameref:unknown:Y .\" ===================== ==== ========== ================== =================== . .\" a table having merged cells cannot be converted to man page . .\" +--------------------+------------------------------------------------------+ .\" |input code |output tags | .\" | +----+----------+------------------+-------------------+ .\" | |name| kind |role |other noticeable fields | .\" +====================+====+==========+==================+===================+ .\" |import X |X | module |imported | | .\" +--------------------+----+----------+------------------+-------------------+ .\" |import X as Y |X | module |indirectlyImported| | .\" | +----+----------+------------------+-------------------+ .\" | |Y | namespace|definition |nameref:module:X | .\" +--------------------+----+----------+------------------+-------------------+ .\" |from X import * |X | module |namespace | | .\" +--------------------+----+----------+------------------+-------------------+ .\" |from X import Y |X | module |namespace | | .\" | +----+----------+------------------+-------------------+ .\" | |Y | unknown |imported |scope:module:X | .\" +--------------------+----+----------+------------------+-------------------+ .\" |from X import Y as Z|X | module |namespace | | .\" | +----+----------+------------------+-------------------+ .\" | |Y | unknown |indirectlyImported|scope:module:X | .\" | +----+----------+------------------+-------------------+ .\" | |Z | unknown |definition |nameref:unknown:Y | .\" +--------------------+----+----------+------------------+-------------------+ . .SS Examples .sp "input.py" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C import X0 .ft P .fi .UNINDENT .UNINDENT .sp "output.tags" with "\-\-options=NONE \-o \- \-\-extras=+r \-\-fields=+rzK input.py" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C X0 input.py /^import X0$/;" kind:module roles:imported .ft P .fi .UNINDENT .UNINDENT .sp A tag for an imported module has \fBmodule\fP kind with \fBimported\fP 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 \fB\-\-extras=+r\fP (or \fB\-\-extras=+{reference}\fP) option for tagging it. "roles:" field enabled with \fB\-\-fields=+r\fP is for recording the module is "imported" to the tag file. .sp "input.py" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C import X1 as Y1 .ft P .fi .UNINDENT .UNINDENT .sp "output.tags" with "\-\-options=NONE \-o \- \-\-extras=+r \-\-fields=+rzK \-\-fields\-Python=+{nameref} input.py" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C X1 input.py /^import X1 as Y1$/;" kind:module roles:indirectlyImported Y1 input.py /^import X1 as Y1$/;" kind:namespace roles:def nameref:module:X1 .ft P .fi .UNINDENT .UNINDENT .sp "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, \fBindirectlyImported\fP role is assigned for "X1". "Y1" is the name for accessing objects defined in the module imported via "X1". For recording this relationship, \fBnameref:\fP field is attached to the tag of "Y1". Instead of \fBmodule\fP kind, \fBnamespace\fP kind is assigned to "Y1" because "Y1" itself isn\(aqt a module. .sp "input.py" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C from X2 import * .ft P .fi .UNINDENT .UNINDENT .sp "output.tags" with "\-\-options=NONE \-o \- \-\-extras=+r \-\-fields=+rzK input.py" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C X2 input.py /^from X2 import *$/;" kind:module roles:namespace .ft P .fi .UNINDENT .UNINDENT .sp 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 \fBnamespace\fP role is attached to "X2" instead of \fBimported\fP\&. .sp "input.py" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C from X3 import Y3 .ft P .fi .UNINDENT .UNINDENT .sp "output.tags" with "\-\-options=NONE \-o \- \-\-extras=+r \-\-fields=+rzKZ input.py" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C X3 input.py /^from X3 import Y3$/;" kind:module roles:namespace Y3 input.py /^from X3 import Y3$/;" kind:unknown scope:module:X3 roles:imported .ft P .fi .UNINDENT .UNINDENT .sp "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 \fBunknown\fP kind to "Y3" because ctags cannot know whether "Y3" is a class, a variable, or a function from the input file. .sp "input.py" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C from X4 import Y4 as Z4 .ft P .fi .UNINDENT .UNINDENT .sp "output.tags" with "\-\-options=NONE \-o \- \-\-extras=+r \-\-fields=+rzKZ input.py" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C X4 input.py /^from X4 import Y4 as Z4$/;" kind:module roles:namespace Y4 input.py /^from X4 import Y4 as Z4$/;" kind:unknown scope:module:X4 roles:indirectlyImported Z4 input.py /^from X4 import Y4 as Z4$/;" kind:unknown roles:def nameref:unknown:Y4 .ft P .fi .UNINDENT .UNINDENT .sp "Y4" is similar to "Y3" of "from X3 import Y3" but the name cannot be used here. \fBindirectlyImported\fP 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. .SH LAMBDA EXPRESSION AND TYPE HINT .SS Summary .sp \fIid = lambda var0: var0\fP .INDENT 0.0 .INDENT 3.5 .TS center; |l|l|l|l|. _ T{ name T} T{ kind T} T{ role T} T{ other noticeable fields T} _ T{ \fIid\fP T} T{ function T} T{ definition T} T{ signature:(\fIvar0\fP) T} _ .TE .UNINDENT .UNINDENT .sp \fIid_t: Callable[[int], int] = lambda var1: var1\fP .INDENT 0.0 .INDENT 3.5 .TS center; |l|l|l|l|. _ T{ name T} T{ kind T} T{ role T} T{ other noticeable fields T} _ T{ \fIid_t\fP T} T{ variable T} T{ definition T} T{ typeref:typename:\fICallable[[int], int]\fP nameref:function:anonFuncN T} _ T{ anonFuncN T} T{ function T} T{ definition T} T{ signature:(\fIvar1\fP) T} _ .TE .UNINDENT .UNINDENT .SS Examples .sp "input.py" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C from typing import Callable id = lambda var0: var0 id_t: Callable[[int], int] = lambda var1: var1 .ft P .fi .UNINDENT .UNINDENT .sp "output.tags" with "\-\-options=NONE \-o \- \-\-sort=no \-\-fields=+KS \-\-fields\-Python=+{nameref} \-\-extras=+{anonymous} input.py" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C id input.py /^id = lambda var0: var0$/;" function signature:(var0) id_t input.py /^id_t: Callable[[int], int] = lambda var1: var1$/;"\e variable typeref:typename:Callable[[int], int] nameref:function:anonFunc84011d2c0101 anonFunc84011d2c0101 input.py /^id_t: Callable[[int], int] = lambda var1: var1$/;"\e function signature:(var1) .ft P .fi .UNINDENT .UNINDENT .sp If a variable ("id") with no type hint is initialized with a lambda expression, ctags assigns \fBfunction\fP kind for the tag of "id". .sp If a variable ("id_t") with a type hint is initialized with a lambda expression, ctags assigns \fBvariable\fP kind for the tag of "id_t" with \fBtyperef:\fP and \fBnameref:\fP fields. ctags fills \fBtyperef:\fP field with the value of the type hint. The way of filling \fBnameref:\fP is a bit complicated. .sp For the lambda expression used in initializing the type\-hint\(aqed variable, ctags creates \fBanonymous\fP extra tag ("anonFunc84011d2c0101"). ctags fills the \fBnameref:\fP field of "id_t" with the name of \fBanonymous\fP extra tag: "nameref:function:anonFunc84011d2c0101". .sp You may think why ctags does so complicated, and why ctags doesn\(aqt emit following tags output for the input: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C id input.py /^id = \e\e$/;" function signature:(var0) id_t input.py /^id_t: \e\e$/;" function typeref:typename:Callable[[int], int] signature:(var1) .ft P .fi .UNINDENT .UNINDENT .sp There is a reason. The other languages of ctags obey the following rule: ctags fills \fBtyperef:\fP 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 \fBtyperef:\fP field should have "typename:int". However, for filling \fBtyperef:\fP with "typename:int", ctags has to analyze "Callable[[int], int]" deeper. We don\(aqt want to do so. .SH SEE ALSO .sp ctags(1), ctags\-client\-tools(7), ctags\-lang\-iPythonCell(7) .\" Generated by docutils manpage writer. .