[Tutor] decorators
Peter Otten
__peter__ at web.de
Fri Jul 23 23:19:00 CEST 2010
Mary Morris wrote:
> I'm trying to compile a list of decorators from the source code at my
> office.
> I did this by doing a
>
> candidate_line.find("@")
>
> because all of our decorators start with the @ symbol. The problem I'm
> having is that the email addresses that are included in the comments are
> getting included in the list that is getting returned.
> I was thinking I could do a candidate_line.find(".com") to set the email
> addresses apart, but how do I tell the computer to not include the lines
> it finds with ".com" in them in the list?
You can use the tokenize module to do the heavy lifting, see
http://docs.python.org/library/tokenize.html
Here's an example:
$ cat find_decos.py
import tokenize
from collections import defaultdict
class Token:
def __init__(self, token):
self.string = token[1]
self.lineno = token[2][0]
def find_decos(instream, filename, decos):
tokens = (Token(token) for token in
tokenize.generate_tokens(instream.readline))
for token in tokens:
if token.string == "@":
lineno = token.lineno
qname = [next(tokens).string]
for token in tokens:
if token.string == ".":
qname.append(next(tokens).string)
else:
break
decos[".".join(qname)].append((lineno, filename))
def main():
import sys
files = sys.argv[1:]
if not files:
# read filenames from stdin
files = (line.strip() for line in sys.stdin)
decorators = defaultdict(list)
for filename in files:
with open(filename) as instream:
find_decos(instream, filename, decorators)
for name in sorted(decorators):
print name
for location in decorators[name]:
print "%8d %s" % location
if __name__ == "__main__":
main()
if False:
def f():
"""
@not_a_decorator
"""
return g
# @not_a_decorator
@alpha
def first(x):
return "user at example.com"
@beta
@gamma . one
def second():
pass
@delta.two.three.four(*args)
@epsilon(42)
def third():
pass
The if False:... suite is of course not a necessary part of the script, it's
just a trick to cram in a few decorators for the script to find when you run
it over itself:
$ python find_decos.py find_decos.py
alpha
50 find_decos.py
beta
54 find_decos.py
delta.two.three.four
59 find_decos.py
epsilon
60 find_decos.py
gamma.one
55 find_decos.py
Alternatively you can feed filenames via stdin:
$ find /usr/lib/python2.6 -name \*.py | python find_decos.py | tail
429 /usr/lib/python2.6/dist-
packages/usbcreator/frontends/kde/frontend.py
434 /usr/lib/python2.6/dist-
packages/usbcreator/frontends/kde/frontend.py
446 /usr/lib/python2.6/dist-
packages/usbcreator/frontends/kde/frontend.py
threaded
166 /usr/lib/python2.6/dist-
packages/softwareproperties/kde/DialogMirror.py
withResolverLog
572 /usr/lib/python2.6/dist-packages/DistUpgrade/DistUpgradeCache.py
858 /usr/lib/python2.6/dist-packages/DistUpgrade/DistUpgradeCache.py
wraps
81 /usr/lib/python2.6/contextlib.py
$
Peter
More information about the Tutor
mailing list