Beispiel #1
0
    def test_countYieldsInOuterScope(self):
        def f():
            x = 0
            yield x
            if x:
                yield x
            else:
                yield
            def f():
                return 4
            class D1:
                def f(self):
                    yield 0
            for x in xrange(3):
                while False:
                    yield x
                else:
                    yield x
            else:
                yield x
            x = [f() for _ in xrange(1000) if f() > 0]
            yield None

        ast = PyAstUtil.pyAstFor(f)
        self.assertEqual(PyAstUtil.countReturnsInOuterScope(ast.body[0]), 0)
        self.assertEqual(PyAstUtil.countYieldsInOuterScope(ast.body[0]), 7)
        self.assertFalse(PyAstUtil.hasReturnInOuterScope(ast.body[0]))
        self.assertTrue(PyAstUtil.hasYieldInOuterScope(ast.body[0]))
        self.assertTrue(PyAstUtil.hasReturnOrYieldInOuterScope(ast.body[0]))
        returnLocs = PyAstUtil.getReturnLocationsInOuterScope(ast.body[0])
        yieldLocs = PyAstUtil.getYieldLocationsInOuterScope(ast.body[0])
        returnLocs = map(lambda x: x - returnLocs[0] if len(returnLocs) > 0 else 0, returnLocs)
        yieldLocs = map(lambda x: x - yieldLocs[0] if len(yieldLocs) > 0 else 0, yieldLocs)
        self.assertEqual(returnLocs, [])
        self.assertEqual(yieldLocs, [0, 2, 4, 12, 14, 16, 18])
Beispiel #2
0
    def test_hasReturnInOuterScope(self):
        def f():
            x = 0
            return x
            if x:
                return x
            else:
                return
            def f():
                yield 4
            class D1:
                def f(self):
                    return 0
            for x in xrange(3):
                while False:
                    return x
                else:
                    return x
            else:
                return x
            x = [f() for _ in xrange(1000) if f() > 0]
            return None

        ast = PyAstUtil.pyAstFor(f)
        self.assertEqual(PyAstUtil.countReturnsInOuterScope(ast.body[0]), 7)
        self.assertEqual(PyAstUtil.countYieldsInOuterScope(ast.body[0]), 0)
        self.assertTrue(PyAstUtil.hasReturnInOuterScope(ast.body[0]))
        self.assertFalse(PyAstUtil.hasYieldInOuterScope(ast.body[0]))
        self.assertTrue(PyAstUtil.hasReturnOrYieldInOuterScope(ast.body[0]))
        returnLocs = PyAstUtil.getReturnLocationsInOuterScope(ast.body[0])
        yieldLocs = PyAstUtil.getYieldLocationsInOuterScope(ast.body[0])
        returnLocs = [x - returnLocs[0] for x in returnLocs]
        yieldLocs = [x - yieldLocs[0] for x in yieldLocs]
        self.assertEqual(returnLocs, [0, 2, 4, 12, 14, 16, 18])
        self.assertEqual(yieldLocs, [])
Beispiel #3
0
    def test_hasReturnInOuterScope(self):
        def f():
            x = 0
            return x
            if x:
                return x
            else:
                return

            def f():
                yield 4

            class D1:
                def f(self):
                    return 0

            for x in xrange(3):
                while False:
                    return x
                else:
                    return x
            else:
                return x
            x = [f() for _ in xrange(1000) if f() > 0]
            return None

        ast = PyAstUtil.pyAstFor(f)
        self.assertEqual(PyAstUtil.countReturnsInOuterScope(ast.body[0]), 7)
        self.assertEqual(PyAstUtil.countYieldsInOuterScope(ast.body[0]), 0)
        self.assertTrue(PyAstUtil.hasReturnInOuterScope(ast.body[0]))
        self.assertFalse(PyAstUtil.hasYieldInOuterScope(ast.body[0]))
        self.assertTrue(PyAstUtil.hasReturnOrYieldInOuterScope(ast.body[0]))
        returnLocs = PyAstUtil.getReturnLocationsInOuterScope(ast.body[0])
        yieldLocs = PyAstUtil.getYieldLocationsInOuterScope(ast.body[0])
        returnLocs = [x - returnLocs[0] for x in returnLocs]
        yieldLocs = [x - yieldLocs[0] for x in yieldLocs]
        self.assertEqual(returnLocs, [0, 2, 4, 12, 14, 16, 18])
        self.assertEqual(yieldLocs, [])
Beispiel #4
0
    def _registerWithBlock(self, objectId, pyObject):
        """
        `_registerWithBlock`: register a `PyforaWithBlock.PyforaWithBlock`
        with `self.objectRegistry`.

        Recursively call `walkPyObject` on the resolvable free variable
        member access chains in the block and on the file object.
        """
        lineNumber = pyObject.lineNumber
        sourceTree = PyAstUtil.pyAstFromText(pyObject.sourceText)
        withBlockAst = PyAstUtil.withBlockAtLineNumber(sourceTree, lineNumber)

        withBlockFun = ast.FunctionDef(
            name="",
            args=ast.arguments(args=[], defaults=[], kwarg=None, vararg=None),
            body=withBlockAst.body,
            decorator_list=[],
            lineno=lineNumber,
            col_offset=0
            )

        if PyAstUtil.hasReturnInOuterScope(withBlockFun):
            raise Exceptions.BadWithBlockError(
                "return statement not supported in pyfora with-block (line %s)" %
                PyAstUtil.getReturnLocationsInOuterScope(withBlockFun)[0])

        if PyAstUtil.hasYieldInOuterScope(withBlockFun):
            raise Exceptions.BadWithBlockError(
                "yield expression not supported in pyfora with-block (line %s)" %
                PyAstUtil.getYieldLocationsInOuterScope(withBlockFun)[0])

        freeVariableMemberAccessChainsWithPositions = \
            self._freeMemberAccessChainsWithPositions(withBlockFun)

        boundValuesInScopeWithPositions = \
            PyAstFreeVariableAnalyses.collectBoundValuesInScope(
                withBlockFun, getPositions=True)

        for boundValueWithPosition in boundValuesInScopeWithPositions:
            val, pos = boundValueWithPosition
            if val not in pyObject.unboundLocals and val in pyObject.boundVariables:
                freeVariableMemberAccessChainsWithPositions.add(
                    PyAstFreeVariableAnalyses.VarWithPosition(var=(val,), pos=pos)
                    )

        try:
            freeVariableMemberAccessChainResolutions = \
                self._resolveFreeVariableMemberAccessChains(
                    freeVariableMemberAccessChainsWithPositions, pyObject.boundVariables
                    )
        except UnresolvedFreeVariableException as e:
            _convertUnresolvedFreeVariableExceptionAndRaise(e, pyObject.sourceFileName)

        try:
            processedFreeVariableMemberAccessChainResolutions = {}
            for chain, (resolution, position) in \
                freeVariableMemberAccessChainResolutions.iteritems():
                processedFreeVariableMemberAccessChainResolutions['.'.join(chain)] = \
                    self.walkPyObject(resolution)
        except UnresolvedFreeVariableExceptionWithTrace as e:
            e.addToTrace(
                Exceptions.makeTraceElement(
                    path=pyObject.sourceFileName,
                    lineNumber=position.lineno
                    )
                )
            raise

        sourceFileId = self.walkPyObject(
            _FileDescription.cachedFromArgs(
                fileName=pyObject.sourceFileName
                )
            )

        self._objectRegistry.defineWithBlock(
            objectId=objectId,
            freeVariableMemberAccessChainsToId=\
                processedFreeVariableMemberAccessChainResolutions,
            sourceFileId=sourceFileId,
            lineNumber=lineNumber
            )
Beispiel #5
0
    def _registerWithBlock(self, objectId, pyObject):
        """
        `_registerWithBlock`: register a `PyforaWithBlock.PyforaWithBlock`
        with `self.objectRegistry`.

        Recursively call `walkPyObject` on the resolvable free variable
        member access chains in the block and on the file object.
        """
        lineNumber = pyObject.lineNumber
        sourceTree = PyAstUtil.pyAstFromText(pyObject.sourceText)
        withBlockAst = PyAstUtil.withBlockAtLineNumber(sourceTree, lineNumber)

        withBlockFun = ast.FunctionDef(name="",
                                       args=ast.arguments(args=[],
                                                          defaults=[],
                                                          kwarg=None,
                                                          vararg=None),
                                       body=withBlockAst.body,
                                       decorator_list=[],
                                       lineno=lineNumber,
                                       col_offset=0)

        if PyAstUtil.hasReturnInOuterScope(withBlockFun):
            raise Exceptions.InvalidPyforaOperation(
                "return statement not supported in pyfora with-block (line %s)"
                % PyAstUtil.getReturnLocationsInOuterScope(withBlockFun)[0])

        if PyAstUtil.hasYieldInOuterScope(withBlockFun):
            raise Exceptions.InvalidPyforaOperation(
                "yield expression not supported in pyfora with-block (line %s)"
                % PyAstUtil.getYieldLocationsInOuterScope(withBlockFun)[0])

        freeVariableMemberAccessChainsWithPositions = \
            self._freeMemberAccessChainsWithPositions(withBlockFun)

        boundValuesInScopeWithPositions = \
            PyAstFreeVariableAnalyses.collectBoundValuesInScope(
                withBlockFun, getPositions=True)

        for boundValueWithPosition in boundValuesInScopeWithPositions:
            val, pos = boundValueWithPosition
            if val not in pyObject.unboundLocals and val in pyObject.boundVariables:
                freeVariableMemberAccessChainsWithPositions.add(
                    PyAstFreeVariableAnalyses.VarWithPosition(var=(val, ),
                                                              pos=pos))

        try:
            freeVariableMemberAccessChainResolutions = \
                self._resolveFreeVariableMemberAccessChains(
                    freeVariableMemberAccessChainsWithPositions, pyObject.boundVariables
                    )
        except UnresolvedFreeVariableException as e:
            _convertUnresolvedFreeVariableExceptionAndRaise(
                e, pyObject.sourceFileName)

        try:
            processedFreeVariableMemberAccessChainResolutions = {}
            for chain, (resolution, position) in \
                freeVariableMemberAccessChainResolutions.iteritems():
                processedFreeVariableMemberAccessChainResolutions['.'.join(chain)] = \
                    self.walkPyObject(resolution)
        except UnresolvedFreeVariableExceptionWithTrace as e:
            e.addToTrace(
                Exceptions.makeTraceElement(path=pyObject.sourceFileName,
                                            lineNumber=position.lineno))
            raise

        sourceFileId = self.walkPyObject(
            _FileDescription.cachedFromArgs(fileName=pyObject.sourceFileName))

        self._objectRegistry.defineWithBlock(
            objectId=objectId,
            freeVariableMemberAccessChainsToId=\
                processedFreeVariableMemberAccessChainResolutions,
            sourceFileId=sourceFileId,
            lineNumber=lineNumber
            )