.. _ctags-lang-python(7): ============================================================== ctags-lang-python ============================================================== ------------------------------------------------------------------- Random notes about tagging python source code with Universal Ctags ------------------------------------------------------------------- :Version: @VERSION@ :Manual group: Universal Ctags :Manual section: 7 SYNOPSIS -------- | **@CTAGS_NAME_EXECUTABLE@** ... --languages=+Python ... | **@CTAGS_NAME_EXECUTABLE@** ... --language-force=Python ... | **@CTAGS_NAME_EXECUTABLE@** ... --map-Python=+.py ... 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` ==== ========== ================== =================== .. ===================== ==== ========== ================== =================== 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 | +--------------------+----+----------+------------------+-------------------+ Examples ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "input.py" .. code-block:: Python import X0 "output.tags" with "--options=NONE -o - --extras=+r --fields=+rzK input.py" .. code-block:: tags X0 input.py /^import X0$/;" kind:module roles:imported 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" .. code-block:: Python import X1 as Y1 "output.tags" with "--options=NONE -o - --extras=+r --fields=+rzK --fields-Python=+{nameref} input.py" .. code-block:: tags 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 "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" .. code-block:: Python from X2 import * "output.tags" with "--options=NONE -o - --extras=+r --fields=+rzK input.py" .. code-block:: tags X2 input.py /^from X2 import *$/;" kind:module roles:namespace 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" .. code-block:: Python from X3 import Y3 "output.tags" with "--options=NONE -o - --extras=+r --fields=+rzKZ input.py" .. code-block:: tags 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 "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" .. code-block:: Python from X4 import Y4 as Z4 "output.tags" with "--options=NONE -o - --extras=+r --fields=+rzKZ input.py" .. code-block:: tags 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 "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" .. code-block:: Python 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" .. code-block:: tags id input.py /^id = lambda var0: var0$/;" function signature:(var0) id_t input.py /^id_t: Callable[[int], int] = lambda var1: var1$/;"\ variable typeref:typename:Callable[[int], int] nameref:function:anonFunc84011d2c0101 anonFunc84011d2c0101 input.py /^id_t: Callable[[int], int] = lambda var1: var1$/;"\ function signature:(var1) 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. SEE ALSO -------- ctags(1), ctags-client-tools(7), ctags-lang-iPythonCell(7)