Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Decorators from a different module #15944

Answered by tausbn
Sim4n6 asked this question in Q&A
Discussion options

I have the following python code:

@s_module.req("aaa")
@deco2
def fct()
 pass

The issue is that my ql code catches only the deco2 with something similar to select all FunctionExpr fe that

predicate is_deco2(FunctionExpr fe) {
 exists(Expr decorator |
 decorator = fe.getADecorator() and decorator.(Name).getId() = "deco2"
 )
}

I am kind of unable to catch the other decorator with the same way by modifying "deco2" to .matches("security%") for instance.?

You must be logged in to vote

I think the reason your query as written isn't working is that in

@security_module.req("aaa")
def fct():
 pass

the decorator is not a Name, but a Call (specifically security_module.req("aaa")), of which the function part (security_module.req, accessible through getFunc) is an Attribute, of which the object (security_module, accessible through getObject) is a Name, whose id matches security%. Thus, you're missing a few levels of syntax in order to match the name.

You could of course extend this to account for all of those additional bits of syntax, but I still think this is going about it the wrong way. Instead, I would again urge you to use API graphs. First identify all references to s...

Replies: 2 comments 2 replies

Comment options

Can you be a bit more specific about what you're trying to achieve here?

E.g. is it "I want to find all functions decorated by a known decorator foo", or "I want to find all decorators of a known function bar"? (Or perhaps some third option?)

Also, it's unclear to me how .matches("security%") relates to your example code, as there is nothing named security in there. Was s_module supposed to be security_module, perhaps?

Either way, you're probably better off working at the level of API graphs, rather than using the AST interface as you do above. For that, it may be helpful to know that decorators are desugared by the Python extractor so that

@s_module.req("aaa")
@deco2
def fct():
 pass

behaves as if the actual code was

fct = (s_module.req("aaa"))(deco2(def fct(): pass))

if we imagine for the moment that Python allowed this kind of "function expression".

You must be logged in to vote
0 replies
Comment options

Can you be a bit more specific about what you're trying to achieve here?
E.g. is it "I want to find all functions decorated by a known decorator foo", or "I want to find all decorators of a known function bar"? (Or perhaps some third option?)

Well, I wanted to identify all functions that have (or have not) the @security_module.req("foo") as one of its decorators.

Also, it's unclear to me how .matches("security%") relates to your example code, as there is nothing named security in there. Was s_module supposed to be security_module, perhaps?

Yes, a little mistake on my side, @security_module.req("foo") is the correct one.

Either way, you're probably better off working at the level of API graphs, rather than using the AST interface as you do above. For that, it may be helpful to know that decorators are desugared by the Python extractor so that

@s_module.req("aaa")
@deco2
def fct():
 pass

behaves as if the actual code was

fct = (s_module.req("aaa"))(deco2(def fct(): pass))

if we imagine for the moment that Python allowed this kind of "function expression".

I am trying something like \

/**
 * @name Decorated functions
 * @kind problem
 * @problem.severity warning
 * @id python/example/empty-scope
 */
import python
class SecurityDecoratedFunctionExpr extends FunctionExpr {
 SecurityDecoratedFunctionExpr() { this.getADecorator().(Name).getId().matches("security%") }
}
from SecurityDecoratedFunctionExpr sdfe, Expr decorator
where
 decorator = sdfe.getADecorator()
select decorator, "This is the one."
You must be logged in to vote
2 replies
Comment options

I think the reason your query as written isn't working is that in

@security_module.req("aaa")
def fct():
 pass

the decorator is not a Name, but a Call (specifically security_module.req("aaa")), of which the function part (security_module.req, accessible through getFunc) is an Attribute, of which the object (security_module, accessible through getObject) is a Name, whose id matches security%. Thus, you're missing a few levels of syntax in order to match the name.

You could of course extend this to account for all of those additional bits of syntax, but I still think this is going about it the wrong way. Instead, I would again urge you to use API graphs. First identify all references to security_module, then getMember will give you attribute accesses on these, and getACall will get you calls of these attribute accesses, and finally for the last getACall, you can ask for the first argument and it'll be the function that you're trying to find the decorators of.

Answer selected by Sim4n6
Comment options

Yes, thank you for the help

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
2 participants

AltStyle によって変換されたページ (->オリジナル) /