472,789 Members | 1,451 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,789 software developers and data experts.

Finding decorators in a file

Probably a bit of weird question. I realise decorators shouldn't be
executed until the function they are defined with are called, but is
there anyway for me to find all the decorates declared in a file when
I import it? Or perhaps anyway to find the decorators by loading the
file by other methods (with out simply parsing it by hand).

Basically what I'm looking for is a way to, given a python file, look
through that file and find all the decorators and the associated
functions, that includes any arguments that the decorator has.

Sorry if this has been asked before but I've googled no end and come
up with nothing so far.

Oct 27 '07 #1
2 1890
On Behalf Of Andrew West
Basically what I'm looking for is a way to, given a python file, look
through that file and find all the decorators and the associated
functions, that includes any arguments that the decorator has.
The inspect module has a function called "findsource"

import inspect
import my_module

lines, line_num = inspect.findsource(my_module)

decorated_lines = [num
for num, line in enumerate(lines)
if line.strip().startswith("@")]

Probably a little more complicated than that -- like what if a function has
two decorators? -- but I think the basic idea will work.

Regards,
Ryan Ginstrom

Oct 27 '07 #2
On Oct 27, 3:14 am, Andrew West <andreww...@gmail.comwrote:
Probably a bit of weird question. I realise decorators shouldn't be
executed until the function they are defined with are called, but is
there anyway for me to find all the decorates declared in a file when
I import it? Or perhaps anyway to find the decorators by loading the
file by other methods (with out simply parsing it by hand).
There is no need for having *parser Angst* in Python. Once you
understand the syntactical structure of the language it's easy to move
on. I show you how to deal with it using EasyExtend for grepping parse
trees ( which is much easier than using regexps for that purpose ).
Alternatively you can use the compiler package. It hides some low
level stuff being present in EE on this level. You need to decide how
you want to reduce mental overhead and achieve simplicity that "fits
your brain".

EasyExtend is available at www.fiber-space.de

Here is a small tutorial:

# purpose -- seeking for decorators and decorated functions in Python
2.5 stdlibs contextlib.py

import inspect
import parser
import symbol
import token

# just import contextlib, keep source and create a parse tree

import contextlib
src = inspect.getsource(contextlib) # keep source
cst = parser.suite(src).tolist() # create concrete syntax tree as
a nested list

# so far its all standard lib stuff...
# ... now something new:

from EasyExtend.csttools import find_node, find_all

functions = find_all(cst, symbol.funcdef)

# You need to know how these nodes are structured to get more
information out of them
# This can be looked up in EasyExtend/Grammar which contains a copy of
Pythons Grammar or
# in the same file in Pythons source distribution. Here are the
relevant rules:

# decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
# decorators: decorator+
# funcdef: [decorators] 'def' NAME parameters ':' suite

# We see immediately that it's not all that simple. Decorators can be
methods and the first name
# in dotted-name can be the name of an object. For demonstration
purposes we simplify our
# assumptions and suppose to have plain function decorators

func_info = {}

for f in functions:

decorator_info = set() # store decorator information here

decorators = find_node(f, symbol.decorators) # we do *not* want
all decorators
# since there might
be those related to
# a closure that is
handled separately
if decorators:
decos = find_all(decorators, symbol.decorator)
for deco in decos:
# token.NAME has structure [1, 'name', line_no]
deco_name = find_node(deco, token.NAME)[1]
args = find_node(deco, symbol.arglist) # ... we
analyze args later
decorator_info.add((deco_name, args))

f_names = find_all(f, token.NAME, level = 1) # set level
information otherwise you
# get all names
defined anywhere in
# funcdef
func_name = f_names[1][1] # the first name is 'def', the
second one the func_name
func_info[func_name] = decorator_info

# Note: you can move from syntax tree representation straightforward
back to a textual
# representation. This requires not much work but the following
import is nevertheless
# conceptual overhead I do not try to explain in detail here:

from EasyExtend.fibers.zero.fiber import unparse # zero represents
*Python* in the larger
# context of
EasyExtend applications
# unparse
transforms a cst of a particular
# grammar back to
source code

for func_name, deco_info in func_info.items():
for (deco_name, deco_args) in deco_info:
print func_name, deco_name, (unparse(deco_args) if deco_args
else "()")

# I get the rather unspectacular result
# nested contextmanager ()
# You might verify this manually...
Oct 27 '07 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Michael Sparks | last post by:
Anyway... At Europython Guido discussed with everyone the outstanding issue with decorators and there was a clear majority in favour of having them, which was good. From where I was sitting it...
4
by: RebelGeekz | last post by:
Just my humble opinion: def bar(low,high): meta: accepts(int,int) returns(float) #more code Use a metadata section, no need to introduce new messy symbols, or mangling our beloved visual...
8
by: Paul Morrow | last post by:
I like many am not wild about the <at> operator. I also don't think that the decorator syntax should be so directly attached to the method, since what we're trying to do is to say something about...
2
by: Guido van Rossum | last post by:
Robert and Python-dev, I've read the J2 proposal up and down several times, pondered all the issues, and slept on it for a night, and I still don't like it enough to accept it. The only reason...
0
by: Anthony Baxter | last post by:
To go along with the 2.4a3 release, here's an updated version of the decorator PEP. It describes the state of decorators as they are in 2.4a3. PEP: 318 Title: Decorators for Functions and...
9
by: Bengt Richter | last post by:
;-) We have @deco def foo(): pass as sugar (unless there's an uncaught exception in the decorator) for def foo(): pass foo = deco(foo) The binding of a class name is similar, and class...
5
by: John Perks and Sarah Mount | last post by:
When handling resources in Python, where the scope of the resource is known, there seem to be two schools of thought: (1) Explicit: f = open(fname) try: # ... finally: f.close()
0
by: Robert Brewer | last post by:
We're trying to get CherryPy 2.1 RC 1 out the door, but setup.py is giving us some problems. In our test suite, we want to test a decorator that we provide. Of course, decorators won't work in...
23
by: Chance Ginger | last post by:
If I define a decorator like: def t(x) : def I(x) : return x return I and use it like: @t(X) def foo(a) :
0
by: Rina0 | last post by:
Cybersecurity engineering is a specialized field that focuses on the design, development, and implementation of systems, processes, and technologies that protect against cyber threats and...
0
by: erikbower65 | last post by:
Using CodiumAI's pr-agent is simple and powerful. Follow these steps: 1. Install CodiumAI CLI: Ensure Node.js is installed, then run 'npm install -g codiumai' in the terminal. 2. Connect to...
0
linyimin
by: linyimin | last post by:
Spring Startup Analyzer generates an interactive Spring application startup report that lets you understand what contributes to the application startup time and helps to optimize it. Support for...
0
by: erikbower65 | last post by:
Here's a concise step-by-step guide for manually installing IntelliJ IDEA: 1. Download: Visit the official JetBrains website and download the IntelliJ IDEA Community or Ultimate edition based on...
0
by: kcodez | last post by:
As a H5 game development enthusiast, I recently wrote a very interesting little game - Toy Claw ((http://claw.kjeek.com/))。Here I will summarize and share the development experience here, and hope it...
14
DJRhino1175
by: DJRhino1175 | last post by:
When I run this code I get an error, its Run-time error# 424 Object required...This is my first attempt at doing something like this. I test the entire code and it worked until I added this - If...
5
by: DJRhino | last post by:
Private Sub CboDrawingID_BeforeUpdate(Cancel As Integer) If = 310029923 Or 310030138 Or 310030152 Or 310030346 Or 310030348 Or _ 310030356 Or 310030359 Or 310030362 Or...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.