예제 #1
0
    def test_stdinCache_find(self):
        stdinCache = StdinCache.StdinCache()
        stdinCache.refreshFromText(
            dedentAndStrip("""
                x+y

                z+h

                def f():
                    def g():
                        return 10
                    return g
                """))

        e1 = compile(ast.parse("x+y"), "<stdin>", 'exec')
        e2 = compile(ast.parse("z+h"), "<stdin>", 'exec')

        self.assertEqual(stdinCache.findCodeLineNumberWithinStdin(e1), 0)
        self.assertEqual(stdinCache.findCodeLineNumberWithinStdin(e2), 2)

        def f():
            def g():
                return 10

            return g

        g = f()

        self.assertEqual(stdinCache.findCodeLineNumberWithinStdin(f.func_code),
                         4)
        self.assertEqual(stdinCache.findCodeLineNumberWithinStdin(g.func_code),
                         5)
예제 #2
0
 def test_stdinCache_trailing_backslash(self):
     stdinCache = StdinCache.StdinCache()
     stdinCache.refreshFromText(
         dedentAndStrip("""
             x+\
             y
             """))
     self.assertEqual(len(stdinCache.blocks), 1)
예제 #3
0
 def test_stdinCache(self):
     stdinCache = StdinCache.StdinCache()
     stdinCache.refreshFromText(
         dedentAndStrip("""
             x
             y
             """))
     self.assertEqual(len(stdinCache.blocks), 2)
예제 #4
0
def getframeinfo(frame, context=1):
    """Get information about a frame or traceback object.

    A tuple of five things is returned: the filename, the line number of
    the current line, the function name, a list of lines of context from
    the source code, and the index of the current line within that list.
    The optional second argument specifies the number of lines of context
    to return, which are centered around the current line."""
    if istraceback(frame):
        lineno = frame.tb_lineno
        frame = frame.tb_frame
    else:
        lineno = frame.f_lineno

    if not isframe(frame):
        raise TypeError(
            '{!r} is not a frame or traceback object'.format(frame))

    filename = getsourcefile(frame) or getfile(frame)

    lines = None
    if filename == "<stdin>":
        lineno = StdinCache.singleton().refreshFromReadline(
        ).findCodeLineNumberWithinStdin(frame.f_code) + 1
        lines = StdinCache.singleton().getlines()

    if context > 0:
        start = lineno - 1 - context // 2
        try:
            if lines is None:
                lines, _ = findsource(frame)
        except IOError:
            if lines is None:
                lines = index = None
        else:
            start = max(start, 1)
            start = max(0, min(start, len(lines) - context))
            lines = lines[start:start + context]
            index = lineno - 1 - start
    else:
        lines = index = None

    return Traceback(filename, lineno, frame.f_code.co_name, lines, index)
예제 #5
0
def getframeinfo(frame, context=1):
    """Get information about a frame or traceback object.

    A tuple of five things is returned: the filename, the line number of
    the current line, the function name, a list of lines of context from
    the source code, and the index of the current line within that list.
    The optional second argument specifies the number of lines of context
    to return, which are centered around the current line."""
    if istraceback(frame):
        lineno = frame.tb_lineno
        frame = frame.tb_frame
    else:
        lineno = frame.f_lineno

    if not isframe(frame):
        raise TypeError('{!r} is not a frame or traceback object'.format(frame))

    filename = getsourcefile(frame) or getfile(frame)

    lines = None
    if filename == "<stdin>":
        lineno = StdinCache.singleton().refreshFromReadline().findCodeLineNumberWithinStdin(frame.f_code) + 1
        lines = StdinCache.singleton().getlines()


    if context > 0:
        start = lineno - 1 - context//2
        try:
            if lines is None:
                lines, _ = findsource(frame)
        except IOError:
            if lines is None:
                lines = index = None
        else:
            start = max(start, 1)
            start = max(0, min(start, len(lines) - context))
            lines = lines[start:start+context]
            index = lineno - 1 - start
    else:
        lines = index = None

    return Traceback(filename, lineno, frame.f_code.co_name, lines, index)
예제 #6
0
    def test_stdinCache_2(self):
        stdinCache = StdinCache.StdinCache()
        stdinCache.refreshFromText(
            dedentAndStrip("""
                def f(arg):
                    if arg:
                        x.y = 3
                    return x

                f()

                """))
        self.assertEqual(len(stdinCache.blocks), 3, stdinCache.blocks)
        self.assertEqual(len(stdinCache.blocks[0]), 4)
예제 #7
0
def getlines(path):
    """return a list of lines for a given path.

    This override is also careful to map "<stdin>" to the full contents of
    the readline buffer.
    """
    if path == "<stdin>":
        return StdinCache.singleton().refreshFromReadline().getlines()

    if path in linesCache_:
        return linesCache_[path]

    if path not in pathExistsOnDiskCache_:
        pathExistsOnDiskCache_[path] = os.path.exists(path)

    if pathExistsOnDiskCache_[path]:
        with open(path, "r") as f:
            linesCache_[path] = f.readlines()
        return linesCache_[path]
    else:
        return None
예제 #8
0
def findsource(pyObject):
    """Return the entire source file and starting line number for an object.

    The argument may be a module, class, method, function, traceback, frame,
    or code object.  The source code is returned as a list of all the lines
    in the file and the line number indexes a line in that list.  An IOError
    is raised if the source code cannot be retrieved."""

    pyFile = getfile(pyObject)
    sourcefile = getsourcefile(pyObject)

    if not sourcefile and pyFile[:1] + pyFile[-1:] != '<>':
        raise IOError('source code not available')

    pyFile = sourcefile if sourcefile else file

    module = getmodule(pyObject, pyFile)
    lines = getlines(pyFile)
    if not lines:
        raise IOError('could not get source code')

    if ismodule(pyObject):
        return lines, 0

    if isclass(pyObject):
        name = pyObject.__name__
        pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
        # find all matching class definitions and if more than one
        # is found, raise a PyforaInspectError
        candidates = []
        for i in range(len(lines)):
            match = pat.match(lines[i])
            if match:
                # add to candidate list
                candidates.append(i)
        if not candidates:
            raise IOError('could not find class definition for %s' % pyObject)
        elif len(candidates) > 1:
            raise PyforaInspectError('could not find class unequivocally: class ' + name)
        else:
            return lines, candidates[0]

    if ismethod(pyObject):
        pyObject = pyObject.im_func
    if isfunction(pyObject):
        pyObject = pyObject.func_code
    if istraceback(pyObject):
        pyObject = pyObject.tb_frame
    if isframe(pyObject):
        pyObject = pyObject.f_code
    if iscode(pyObject):
        if pyFile == "<stdin>":
            #the "co_firstlineno" variable is wrong in this case.
            #we need to find the actual line number
            lnum = StdinCache.singleton().refreshFromReadline().findCodeLineNumberWithinStdin(pyObject)
        else:
            if not hasattr(pyObject, 'co_firstlineno'):
                raise IOError('could not find function definition')
            lnum = pyObject.co_firstlineno - 1
        pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
        while lnum > 0:
            if pat.match(lines[lnum]): break
            lnum = lnum - 1
        return lines, lnum
    raise IOError('could not find code object')