1
###############################################################################
3
# Purpose: Generate Python Tags #
4
# Author: Cody Precord <cprecord@editra.org> #
5
# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
6
# License: wxWindows License #
7
###############################################################################
15
Generate a DocStruct object that captures the structure of a python document.
16
It supports parsing for global and class variables, class, method, and function
19
@todo: add back support for class variables
20
@todo: document functions
24
__author__ = "Cody Precord <cprecord@editra.org>"
25
__svnid__ = "$Id: pytags.py 69297 2011-10-03 15:53:48Z CJP $"
26
__revision__ = "$Revision: 69297 $"
28
#--------------------------------------------------------------------------#
32
from pygments import highlight
33
from pygments.token import Token
34
from pygments.lexers import get_lexer_by_name
35
from pygments.formatter import Formatter
37
#--------------------------------------------------------------------------#
39
class PyFormatter(Formatter):
41
def format(self, tokensource, outfile):
42
self.rtags = taglib.DocStruct()
43
self.rtags.SetElementDescription('function', "Function Definitions")
44
self.rtags.SetElementDescription('class', "Class Definitions")
52
# Parse the file into tokens and values
53
for ttype, value in tokensource:
55
code_lines.append((line_count, current_line))
57
line_count += value.count('\n')
59
current_line.append((ttype, value))
61
self.getCFV(code_lines)
63
def _getLevel(self, line):
72
def pushPopScope(self, level):
73
"""Push a scope onto the stack. If less than previous scope
74
it will pop levels until it finds a matching indent level.
78
for lvl in self._levels:
84
self._levels = nlevels
86
def insertClass(self, line, num, container_list):
87
"""Insert a class into the container"""
88
cname = parselib.GetTokenValue(line, Token.Name.Class)
89
clevel = self._getLevel(line)
94
ctag = taglib.Class(cname, num)
95
self.rtags.AddClass(ctag)
99
for l, c, ob in reversed(container_list):
101
ctag = taglib.Class(cname, num, c)
102
ob.AddElement('class', ctag)
106
container_list.append((clevel, cname, ctag))
108
def insertFunction(self, line, num, container_list):
109
fname = parselib.GetTokenValue(line, Token.Name.Function)
110
flevel = self._getLevel(line)
115
ftag = taglib.Function(fname, num)
116
self.rtags.AddFunction(ftag)
120
for l, c, ob in reversed(container_list):
122
if isinstance(ob, taglib.Class):
123
ftag = taglib.Method(fname, num, c)
126
ftag = taglib.Function(fname, num, c)
127
ob.AddElement('function', ftag)
131
container_list.append((flevel, fname, ftag))
133
def getCFV(self, code_lines):
138
for num, line in code_lines:
141
ltxt = u"".join([l[1].strip() for l in line])
142
if len(ltxt) and not ltxt.startswith(u"#"):
143
if parselib.BeginsWithAnyOf(line, Token.Keyword,
144
(u"def", u"class", u"if", u"else")):
145
self.pushPopScope(self._getLevel(line))
146
if len(self._levels) == 1:
147
container_list = [(0, u"", self.rtags)]
151
if parselib.HasToken(line, Token.Keyword, "def"):
152
self.insertFunction(line, num, container_list)
156
elif parselib.HasToken(line, Token.Keyword, "class"):
157
self.insertClass(line, num, container_list)
159
# Global Variable Only
161
elif parselib.HasToken(line, Token.Operator, "="):
162
vname = parselib.GetTokenValue(line, Token.Name);
163
flevel = self._getLevel(line)
166
if not vname in vset:
167
self.rtags.AddVariable(taglib.Variable(vname, num))
170
except parselib.TokenNotFound:
177
#-----------------------------------------------------------------------------#
179
def GenerateTags(buff):
180
"""GenTag interface method
181
@return: taglib.DocStruct
184
formatter = PyFormatter()
185
highlight(buff.read(), get_lexer_by_name("python"), formatter)
186
return formatter.getTags()
188
#-----------------------------------------------------------------------------#
190
if __name__ == '__main__':
193
fhandle = open(sys.argv[1])
196
tags = GenerateTags(StringIO.StringIO(txt))
197
print "\n\nVARIABLES:"
198
for var in tags.GetVariables():
199
print "%s [%d]" % (var.GetName(), var.GetLine())
200
print "\n\nFUNCTIONS:"
201
for fun in tags.GetFunctions():
202
print "%s [%d]" % (fun.GetName(), fun.GetLine())
205
for c in tags.GetClasses():
206
print "* %s [%d]" % (c.GetName(), c.GetLine())
209
# get var and methods does not exist ( any more ?? )
210
# for var in c.GetVariables():
211
# print "VAR: ", var.GetName()
212
# for meth in c.GetMethods():
213
# print " %s [%d]" % (meth.GetName(), meth.GetLine())