PyCG icon indicating copy to clipboard operation
PyCG copied to clipboard

[need help] Is this uncomplete call graph within expectation?

Open LeeSureman opened this issue 3 years ago • 7 comments

Hello, I have read your work "PyCG: Practical Call Graph Generation in Python", and think it is valuable, helpful and insightful. However, when I try to scan this file as following:

class tmp_C:
    def tmp_f_in_c(self):
        print('tmp_f_in_c called')
        return None

def tmp_f():
    a = tmp_C
    returned = a()
    return returned


def f_sample():

    tmp_c = tmp_f()
    tmp_c.tmp_f_in_c()

the extracted callgraph is {"small": ["small.f_sample"], "small.tmp_C.tmp_f_in_c": ["<builtin>.print"], "<builtin>.print": [], "small.tmp_f": [], "small.f_sample": ["small.tmp_f"]} there is not 'small.tmp_C.tmp_f_in_c' in 'small.f_sample' 's calling function while 'small.f_sample' has called 'small.tmp_C.tmp_f_in_c'. So I'd ask whether your callgraph generator could extract this complete callgraph within expectation? It will be a great and wonderful help if you response me. Thank you!

LeeSureman avatar Mar 01 '22 13:03 LeeSureman

PyCG should produce a complete call graph in this case. This is probably a bug with the generator, I'll investigate when I got the bandwidth and get back to you.

vitsalis avatar Mar 01 '22 14:03 vitsalis

Very thank you for your quick response!! It will be a great help for me. Actually I can provide another code snippet which may be related to the code above or an extension (about external library) of the code above. This code sample is as following:

def f_sample_2():
    import numpy
    import torch

    numpy_array = numpy.ones(shape=[2,3])
    torch_tensor = torch.ones(size=[2,3])

    numpy_array.max()
    torch_tensor.max()

The extracted callgraph is ["numpy.ones", "torch.ones"] I think it maybe lack numpy.ndarray.max and torch.Tensor.max (Am I right? or is it within expectation? )

this new case involves the external library like numpy and torch. (I see your code involves handling external library, so in expectation your code can give the complete callgraph in this case?) Looking forward to receiving your response.

LeeSureman avatar Mar 01 '22 14:03 LeeSureman

Hello, I have read your work "PyCG: Practical Call Graph Generation in Python", and think it is valuable, helpful and insightful. However, when I try to scan this file as following:

class tmp_C:
    def tmp_f_in_c(self):
        print('tmp_f_in_c called')
        return None

def tmp_f():
    a = tmp_C
    returned = a()
    return returned


def f_sample():

    tmp_c = tmp_f()
    tmp_c.tmp_f_in_c()

the extracted callgraph is {"small": ["small.f_sample"], "small.tmp_C.tmp_f_in_c": ["<builtin>.print"], "<builtin>.print": [], "small.tmp_f": [], "small.f_sample": ["small.tmp_f"]} there is not 'small.tmp_C.tmp_f_in_c' in 'small.f_sample' 's calling function while 'small.f_sample' has called 'small.tmp_C.tmp_f_in_c'. So I'd ask whether your callgraph generator could extract this complete callgraph within expectation? It will be a great and wonderful help if you response me. Thank you!

I think PyCG is trying to look for class tmp_c but tmp_c is not defined anywhere in scope. It will work if you change tmp_c.tmp_f_in_c() to tmp_C.tmp_f_in_c()

{"small": [], "small.tmp_C.tmp_f_in_c": ["<builtin>.print"], "<builtin>.print": [], "small.tmp_f": [], "small.f_sample": ["small.tmp_f", "small.tmp_C.tmp_f_in_c"]}

seanxiaoyan avatar Mar 06 '22 04:03 seanxiaoyan

Hello, I have read your work "PyCG: Practical Call Graph Generation in Python", and think it is valuable, helpful and insightful. However, when I try to scan this file as following:

class tmp_C:
    def tmp_f_in_c(self):
        print('tmp_f_in_c called')
        return None

def tmp_f():
    a = tmp_C
    returned = a()
    return returned


def f_sample():

    tmp_c = tmp_f()
    tmp_c.tmp_f_in_c()

the extracted callgraph is {"small": ["small.f_sample"], "small.tmp_C.tmp_f_in_c": ["<builtin>.print"], "<builtin>.print": [], "small.tmp_f": [], "small.f_sample": ["small.tmp_f"]} there is not 'small.tmp_C.tmp_f_in_c' in 'small.f_sample' 's calling function while 'small.f_sample' has called 'small.tmp_C.tmp_f_in_c'. So I'd ask whether your callgraph generator could extract this complete callgraph within expectation? It will be a great and wonderful help if you response me. Thank you!

I think PyCG is trying to look for class tmp_c but tmp_c is not defined anywhere in scope. It will work if you change tmp_c.tmp_f_in_c() to tmp_C.tmp_f_in_c()

{"small": [], "small.tmp_C.tmp_f_in_c": ["<builtin>.print"], "<builtin>.print": [], "small.tmp_f": [], "small.f_sample": ["small.tmp_f", "small.tmp_C.tmp_f_in_c"]}

Thank you for your response and help! Since 'tmp_c' is the instance of 'tmp_C' as defined in 'tmp_f', do you mean PYCG technically can not detect 'tmp_c' is the instance of 'tmp_C'?

LeeSureman avatar Mar 06 '22 05:03 LeeSureman

Hello, I have read your work "PyCG: Practical Call Graph Generation in Python", and think it is valuable, helpful and insightful. However, when I try to scan this file as following:

class tmp_C:
    def tmp_f_in_c(self):
        print('tmp_f_in_c called')
        return None

def tmp_f():
    a = tmp_C
    returned = a()
    return returned


def f_sample():

    tmp_c = tmp_f()
    tmp_c.tmp_f_in_c()

the extracted callgraph is {"small": ["small.f_sample"], "small.tmp_C.tmp_f_in_c": ["<builtin>.print"], "<builtin>.print": [], "small.tmp_f": [], "small.f_sample": ["small.tmp_f"]} there is not 'small.tmp_C.tmp_f_in_c' in 'small.f_sample' 's calling function while 'small.f_sample' has called 'small.tmp_C.tmp_f_in_c'. So I'd ask whether your callgraph generator could extract this complete callgraph within expectation? It will be a great and wonderful help if you response me. Thank you!

I think PyCG is trying to look for class tmp_c but tmp_c is not defined anywhere in scope. It will work if you change tmp_c.tmp_f_in_c() to tmp_C.tmp_f_in_c()

{"small": [], "small.tmp_C.tmp_f_in_c": ["<builtin>.print"], "<builtin>.print": [], "small.tmp_f": [], "small.f_sample": ["small.tmp_f", "small.tmp_C.tmp_f_in_c"]}

Thank you for your response and help! Since 'tmp_c' is the instance of 'tmp_C' as defined in 'tmp_f', do you mean PYCG technically can not detect 'tmp_c' is the instance of 'tmp_C'?

This is causing issue

    a = tmp_C
    returned = a()

PyCG can detect instance if the code looks like this

class tmp_C:
    def tmp_f_in_c(self):
        print('tmp_f_in_c called')
        return None

def tmp_f():
    a = tmp_C()
    return a


def f_sample():
    tmp_c = tmp_f()
    tmp_c.tmp_f_in_c()

seanxiaoyan avatar Mar 06 '22 05:03 seanxiaoyan

@seanxiaoyan yes, it is rare but it is grammatical in python.. Since the author says PYCG should detect it, I will wait for him to figure out it..

LeeSureman avatar Mar 06 '22 05:03 LeeSureman

hello, would you mind me asking when this bug can be fixed?

LeeSureman avatar Mar 12 '22 15:03 LeeSureman

Closing due to archival of repository.

vitsalis avatar Nov 26 '23 07:11 vitsalis