1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
|
.. _ctags-lang-python(7):
==============================================================
ctags-lang-python
==============================================================
Random notes about tagging python source code with Universal Ctags
:Version: 6.2.1
:Manual group: Universal Ctags
:Manual section: 7
SYNOPSIS
--------
| **ctags** ... --languages=+Python ...
| **ctags** ... --language-force=Python ...
| **ctags** ... --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.
VERSIONS
--------
Change since "0.0"
~~~~~~~~~~~~~~~~~~
* New role ``entryPoint`` for ``module`` kind
PythonEntryPoints parser emits tag entries having this role.
* New role ``entryPoint`` for ``function`` kind
PythonEntryPoints parser emits tag entries having this role.
SEE ALSO
--------
:ref:`ctags(1) <ctags(1)>`, :ref:`ctags-client-tools(7) <ctags-client-tools(7)>`, :ref:`ctags-lang-iPythonCell(7) <ctags-lang-iPythonCell(7)>`
|