def buildParameterSpec(name, node, source_ref):
    kind = getKind(node)

    assert kind in ("FunctionDef", "Lambda"), "unsupported for kind " + kind

    def extractArg(arg):
        if type(arg) is str or arg is None:
            return arg
        elif getKind(arg) == "Name":
            return arg.id
        elif getKind(arg) == "arg":
            return arg.arg
        elif getKind(arg) == "Tuple":
            return tuple(extractArg(arg) for arg in arg.elts)
        else:
            assert False, getKind(arg)

    result = ParameterSpec(
        name=name,
        normal_args=[extractArg(arg) for arg in node.args.args],
        kw_only_args=[extractArg(arg) for arg in node.args.kwonlyargs]
        if Utils.python_version >= 300 else [],
        list_star_arg=extractArg(node.args.vararg),
        dict_star_arg=extractArg(node.args.kwarg),
        default_count=len(node.args.defaults))

    message = result.checkValid()

    if message is not None:
        SyntaxErrors.raiseSyntaxError(message, source_ref)

    return result
Exemple #2
0
def _markAsGenerator(provider, node, source_ref):
    if provider.isPythonModule():
        SyntaxErrors.raiseSyntaxError(
            "'yield' outside function", source_ref,
            None if Utils.python_version < 300 else node.col_offset)

    provider.markAsGenerator()
def buildReturnNode(provider, node, source_ref):
    if not provider.isExpressionFunctionBody() or \
       provider.isClassDictCreation():
        SyntaxErrors.raiseSyntaxError(
            "'return' outside function",
            source_ref,
            None if Utils.python_version < 300 else (
                node.col_offset
                  if provider.isPythonModule() else
                node.col_offset+4
            )
        )

    expression = buildNode(provider, node.value, source_ref, allow_none = True)

    if expression is None:
        expression = ExpressionConstantRef(
            constant      = None,
            source_ref    = source_ref,
            user_provided = True
        )


    return makeTryFinallyIndicator(
        provider    = provider,
        statement   = StatementReturn(
            expression = expression,
            source_ref = source_ref
        ),
        is_loop_exit = False
    )
    def _handleNonLocal(self, node):
        # Take closure variables for non-local declarations.

        for non_local_names, source_ref in node.getNonlocalDeclarations():
            for non_local_name in non_local_names:
                variable = node.getClosureVariable(
                    variable_name = non_local_name
                )

                node.registerProvidedVariable( variable )

                if variable.isModuleVariableReference():
                    SyntaxErrors.raiseSyntaxError(
                        "no binding for nonlocal '%s' found" % (
                            non_local_name
                        ),
                        source_ref   = None
                                         if isFullCompat() and \
                                         python_version < 340 else
                                       source_ref,
                        display_file = not isFullCompat() or \
                                       python_version >= 340,
                        display_line = not isFullCompat() or \
                                       python_version >= 340
                    )
Exemple #5
0
def buildStatementContinueLoop(node, source_ref):
    if getBuildContext() == "finally":
        if not Options.isFullCompat() or Utils.python_version >= 300:
            col_offset = node.col_offset - 9
        else:
            col_offset = None

        if Utils.python_version >= 300 and Options.isFullCompat():
            source_line = ""
        else:
            source_line = None

        SyntaxErrors.raiseSyntaxError(
            "'continue' not supported inside 'finally' clause",
            source_ref,
            col_offset  = col_offset,
            source_line = source_line
        )


    return makeTryFinallyIndicator(
        statement    = StatementContinueLoop(
            source_ref = source_ref
        ),
        is_loop_exit = True
    )
Exemple #6
0
def buildReturnNode(provider, node, source_ref):
    if not provider.isExpressionFunctionBody() or \
       provider.isClassDictCreation():
        SyntaxErrors.raiseSyntaxError(
            "'return' outside function",
            source_ref,
            None if Utils.python_version < 300 else (
                node.col_offset
                  if provider.isPythonModule() else
                node.col_offset+4
            )
        )

    expression = buildNode(provider, node.value, source_ref, allow_none = True)

    if expression is None:
        expression = ExpressionConstantRef(
            constant      = None,
            source_ref    = source_ref,
            user_provided = True
        )


    return makeTryFinallyIndicator(
        statement    = StatementReturn(
            expression = expression,
            source_ref = source_ref
        ),
        is_loop_exit = False
    )
Exemple #7
0
def handleGlobalDeclarationNode(provider, node, source_ref):
    # The source reference of the global really doesn't matter, pylint: disable=W0613

    # On the module level, there is nothing to do.
    if provider.isPythonModule():
        return None

    # Need to catch the error of declaring a parameter variable as global ourselves
    # here. The AST parsing doesn't catch it.
    try:
        parameters = provider.getParameters()

        for variable_name in node.names:
            if variable_name in parameters.getParameterNames():
                SyntaxErrors.raiseSyntaxError(
                    reason="name '%s' is %s and global" %
                    (variable_name,
                     "local" if Utils.python_version < 300 else "parameter"),
                    source_ref=provider.getSourceReference())
    except AttributeError:
        pass

    module = provider.getParentModule()

    for variable_name in node.names:
        module_variable = module.getVariableForAssignment(
            variable_name=variable_name)

        closure_variable = provider.addClosureVariable(
            variable=module_variable, global_statement=True)

        provider.registerProvidedVariable(variable=closure_variable)

    return None
Exemple #8
0
def buildReturnNode(provider, node, source_ref):
    if not provider.isExpressionFunctionBody() or \
       provider.isClassDictCreation():
        SyntaxErrors.raiseSyntaxError(
            "'return' outside function",
            source_ref,
            None if Utils.python_version < 300 else (
                node.col_offset
                  if provider.isPythonModule() else
                node.col_offset+4
            )
        )

    if node.value is not None:
        return StatementReturn(
            expression = buildNode( provider, node.value, source_ref ),
            source_ref = source_ref
        )
    else:
        return StatementReturn(
            expression = ExpressionConstantRef(
                constant      = None,
                source_ref    = source_ref,
                user_provided = True
            ),
            source_ref = source_ref
        )
    def _attachVariable(node, provider):
        # print "Late reference", node.getVariableName(), "for", provider, "caused at", node, "of", node.getParent()

        variable_name = node.getVariableName()

        was_taken = provider.hasTakenVariable(variable_name)

        variable = provider.getVariableForReference(
            variable_name=variable_name)

        node.setVariable(variable)

        # Need to catch functions with "exec" and closure variables not allowed.
        if python_version < 300 and \
           not was_taken and \
           provider.isExpressionFunctionBody() and \
           variable.getOwner() is not provider:
            parent_provider = provider.getParentVariableProvider()

            while parent_provider.isExpressionFunctionBody() and \
                  parent_provider.isClassDictCreation():
                parent_provider = parent_provider.getParentVariableProvider()

            if parent_provider.isExpressionFunctionBody() and \
               parent_provider.isUnqualifiedExec():
                SyntaxErrors.raiseSyntaxError(
                    reason       = PythonVersions.\
                                     getErrorMessageExecWithNestedFunction() % \
                                     parent_provider.getName(),
                    source_ref   = parent_provider.getExecSourceRef(),
                    col_offset   = None,
                    display_file = True,
                    display_line = True,
                    source_line  = None
                )
def buildStatementContinueLoop(provider, node, source_ref):
    if getBuildContext() == "finally":
        if not Options.isFullCompat() or Utils.python_version >= 300:
            col_offset = node.col_offset - 9
        else:
            col_offset = None

        if Utils.python_version >= 300 and Options.isFullCompat():
            source_line = ""
        else:
            source_line = None

        SyntaxErrors.raiseSyntaxError(
            "'continue' not supported inside 'finally' clause",
            source_ref,
            col_offset  = col_offset,
            source_line = source_line
        )


    return makeTryFinallyIndicator(
        provider     = provider,
        statement    = StatementContinueLoop(
            source_ref = source_ref
        ),
        is_loop_exit = True
    )
Exemple #11
0
    def _attachVariable(self, node, provider):
        # print "Late reference", node.getVariableName(), "for", provider, "caused at", node, "of", node.getParent()

        variable = provider.getVariableForReference(
            variable_name=node.getVariableName())

        node.setVariable(variable)

        # Need to catch functions with "exec" not allowed.
        if python_version < 300 and \
           provider.isExpressionFunctionBody() and \
           variable.isReference() and \
             (not variable.isModuleVariableReference() or \
              not variable.isFromGlobalStatement() ):

            parent_provider = provider.getParentVariableProvider()

            while parent_provider.isExpressionFunctionBody() and \
                  parent_provider.isClassDictCreation():
                parent_provider = parent_provider.getParentVariableProvider()

            if parent_provider.isExpressionFunctionBody() and \
               parent_provider.isUnqualifiedExec():
                SyntaxErrors.raiseSyntaxError(
                    reason="""\
unqualified exec is not allowed in function '%s' it \
contains a nested function with free variables""" % parent_provider.getName(),
                    source_ref=parent_provider.getExecSourceRef(),
                    col_offset=None,
                    display_file=True,
                    display_line=True,
                    source_line=None)
def handleNonlocalDeclarationNode(provider, node, source_ref):
    # The source reference of the nonlocal really doesn't matter.
    # pylint: disable=W0613

    # Need to catch the error of declaring a parameter variable as global
    # ourselves here. The AST parsing doesn't catch it, but we can do it here.
    parameters = provider.getParameters()

    for variable_name in node.names:
        if variable_name in parameters.getParameterNames():
            SyntaxErrors.raiseSyntaxError(
                reason       = "name '%s' is parameter and nonlocal" % (
                    variable_name
                ),
                source_ref   = None
                                 if Options.isFullCompat() and \
                                 Utils.python_version < 340 else
                               source_ref,
                display_file = not Options.isFullCompat() or \
                               Utils.python_version >= 340,
                display_line = not Options.isFullCompat() or \
                               Utils.python_version >= 340
            )

    provider.addNonlocalsDeclaration(node.names, source_ref)

    return None
def buildParameterSpec( name, node, source_ref ):
    kind = getKind( node )

    assert kind in ( "FunctionDef", "Lambda" ), "unsupported for kind " + kind

    def extractArg( arg ):
        if getKind( arg ) == "Name":
            return arg.id
        elif getKind( arg ) == "arg":
            return arg.arg
        elif getKind( arg ) == "Tuple":
            return tuple( extractArg( arg ) for arg in arg.elts )
        else:
            assert False, getKind( arg )

    result = ParameterSpec(
        name           = name,
        normal_args    = [ extractArg( arg ) for arg in node.args.args ],
        kw_only_args   = [ extractArg( arg ) for arg in node.args.kwonlyargs ] if Utils.python_version >= 300 else [],
        list_star_arg  = node.args.vararg,
        dict_star_arg  = node.args.kwarg,
        default_count  = len( node.args.defaults )
    )

    message = result.checkValid()

    if message is not None:
        SyntaxErrors.raiseSyntaxError(
            message,
            source_ref
        )

    return result
Exemple #14
0
def handleGlobalDeclarationNode( provider, node, source_ref ):

    if not source_ref.isExecReference():
        # On the module level, there is nothing to do.
        if provider.isPythonModule():
            return None

        # Need to catch the error of declaring a parameter variable as global ourselves
        # here. The AST parsing doesn't catch it.
        try:
            parameters = provider.getParameters()

            for variable_name in node.names:
                if variable_name in parameters.getParameterNames():
                    SyntaxErrors.raiseSyntaxError(
                        reason     = "name '%s' is %s and global" % (
                            variable_name,
                            "local" if Utils.python_version < 300 else "parameter"
                        ),
                        source_ref = provider.getSourceReference()
                    )
        except AttributeError:
            pass

    module = provider.getParentModule()

    for variable_name in node.names:
        closure_variable = None

        # Re-use already taken global variables, in order to avoid creating yet
        # another instance, esp. as the markups could then potentially not be
        # shared.
        if provider.hasTakenVariable( variable_name ):
            closure_variable = provider.getTakenVariable( variable_name )

            if not closure_variable.isModuleVariableReference():
                closure_variable = None

        if closure_variable is None:
            module_variable = module.getVariableForAssignment(
                variable_name = variable_name
            )

            closure_variable = provider.addClosureVariable(
                variable = module_variable
            )

        assert closure_variable.isModuleVariableReference()

        closure_variable.markFromGlobalStatement()

        if source_ref.isExecReference():
            closure_variable.markFromExecStatement()

        provider.registerProvidedVariable(
            variable = closure_variable
        )

    return None
def _markAsGenerator(provider, node, source_ref):
    if provider.isPythonModule():
        SyntaxErrors.raiseSyntaxError(
            "'yield' outside function",
            source_ref,
            None if Utils.python_version < 300 else node.col_offset
        )

    provider.markAsGenerator()
Exemple #16
0
def _readSourceCodeFromFilename3(source_filename):
    with open(source_filename, "rb") as source_file:
        source_code = source_file.read()

    if source_code.startswith(b'\xef\xbb\xbf'):
        source_code = source_code[3:]

    new_line = source_code.find(b"\n")

    if new_line is not -1:
        line = source_code[: new_line]

        line_match = re.search(b"coding[:=]\\s*([-\\w.]+)", line)

        if line_match:
            encoding = line_match.group(1).decode("ascii")

            # Detect encoding problem, as decode won't raise the compatible
            # thing.
            try:
                import codecs
                codecs.lookup(encoding)
            except LookupError:
                if Utils.python_version >= 341 or \
                   (Utils.python_version >= 335 and \
                    Utils.python_version < 340) or \
                   (Utils.python_version >= 323 and \
                    Utils.python_version < 330):
                    reason = "encoding problem: %s" % encoding
                else:
                    reason = "unknown encoding: %s" % encoding

                SyntaxErrors.raiseSyntaxError(
                    reason       = reason,
                    source_ref   = SourceCodeReferences.fromFilename(
                        source_filename,
                        None
                    ),
                    display_line = False
                )

            return source_code[ new_line : ].decode(encoding)

        new_line = source_code.find(b"\n", new_line+1)

        if new_line is not -1:
            line = source_code[ : new_line ]

            line_match = re.search(b"coding[:=]\\s*([-\\w.]+)", line)

            if line_match:
                encoding = line_match.group(1).decode("ascii")

                return "\n" + source_code[ new_line : ].decode(encoding)

    return source_code.decode("utf-8")
Exemple #17
0
def handleGlobalDeclarationNode(provider, node, source_ref):

    if not source_ref.isExecReference():
        # On the module level, there is nothing to do.
        if provider.isPythonModule():
            return None

        # Need to catch the error of declaring a parameter variable as global ourselves
        # here. The AST parsing doesn't catch it.
        try:
            parameters = provider.getParameters()

            for variable_name in node.names:
                if variable_name in parameters.getParameterNames():
                    SyntaxErrors.raiseSyntaxError(
                        reason="name '%s' is %s and global" %
                        (variable_name, "local"
                         if Utils.python_version < 300 else "parameter"),
                        source_ref=provider.getSourceReference())
        except AttributeError:
            pass

    module = provider.getParentModule()

    for variable_name in node.names:
        closure_variable = None

        # Re-use already taken global variables, in order to avoid creating yet
        # another instance, esp. as the markups could then potentially not be
        # shared.
        if provider.hasTakenVariable(variable_name):
            closure_variable = provider.getTakenVariable(variable_name)

            if not closure_variable.isModuleVariableReference():
                closure_variable = None

        if closure_variable is None:
            module_variable = module.getVariableForAssignment(
                variable_name=variable_name)

            closure_variable = provider.addClosureVariable(
                variable=module_variable)

        assert closure_variable.isModuleVariableReference()

        closure_variable.markFromGlobalStatement()

        if source_ref.isExecReference():
            closure_variable.markFromExecStatement()

        provider.registerProvidedVariable(variable=closure_variable)

    return None
Exemple #18
0
def _readSourceCodeFromFilename3(source_filename):
    with open(source_filename, "rb") as source_file:
        source_code = source_file.read()

    if source_code.startswith(b'\xef\xbb\xbf'):
        source_code = source_code[3:]

    new_line = source_code.find(b"\n")

    if new_line is not -1:
        line = source_code[:new_line]

        line_match = re.search(b"coding[:=]\\s*([-\\w.]+)", line)

        if line_match:
            encoding = line_match.group(1).decode("ascii")

            # Detect encoding problem, as decode won't raise the compatible
            # thing.
            try:
                import codecs
                codecs.lookup(encoding)
            except LookupError:
                if Utils.python_version >= 341 or \
                   (Utils.python_version >= 335 and \
                    Utils.python_version < 340) or \
                   (Utils.python_version >= 323 and \
                    Utils.python_version < 330):
                    reason = "encoding problem: %s" % encoding
                else:
                    reason = "unknown encoding: %s" % encoding

                SyntaxErrors.raiseSyntaxError(
                    reason=reason,
                    source_ref=SourceCodeReferences.fromFilename(
                        source_filename, None),
                    display_line=False)

            return source_code[new_line:].decode(encoding)

        new_line = source_code.find(b"\n", new_line + 1)

        if new_line is not -1:
            line = source_code[:new_line]

            line_match = re.search(b"coding[:=]\\s*([-\\w.]+)", line)

            if line_match:
                encoding = line_match.group(1).decode("ascii")

                return "\n" + source_code[new_line:].decode(encoding)

    return source_code.decode("utf-8")
Exemple #19
0
    def onEnterNode(self, node):
        assert python_version < 300

        if node.isStatementDelVariable():
            variable = node.getTargetVariableRef().getVariable()

            if not variable.isModuleVariable() and \
               isSharedLogically(variable):
                SyntaxErrors.raiseSyntaxError(
                    reason="""\
can not delete variable '%s' referenced in nested scope""" %
                    (variable.getName()),
                    source_ref=(None if isFullCompat() else
                                node.getSourceReference()),
                    display_file=not isFullCompat(),
                    display_line=not isFullCompat())
def checkFutureImportsOnlyAtStart(body):
    # Check if a __future__ imports really were at the beginning of the file.
    for node in body:
        if node in _future_import_nodes:
            _future_import_nodes.remove(node)
        else:
            if _future_import_nodes:
                SyntaxErrors.raiseSyntaxError(
                    reason     = """\
from __future__ imports must occur at the beginning of the file""",
                    col_offset = 1
                      if Utils.python_version >= 300 or \
                      not Options.isFullCompat() else
                    None,
                    source_ref = _future_import_nodes[0].source_ref
                )
Exemple #21
0
def buildYieldNode(provider, node, source_ref):
    if provider.isPythonModule():
        SyntaxErrors.raiseSyntaxError(
            "'yield' outside function", source_ref,
            None if Utils.python_version < 300 else node.col_offset)

    provider.markAsGenerator()

    if node.value is not None:
        return ExpressionYield(expression=buildNode(provider, node.value,
                                                    source_ref),
                               source_ref=source_ref)
    else:
        return ExpressionYield(expression=ExpressionConstantRef(
            constant=None, source_ref=source_ref),
                               source_ref=source_ref)
Exemple #22
0
def _readSourceCodeFromFilename2(source_filename):
    # Detect the encoding.
    encoding = _detectEncoding2(source_filename)

    with open(source_filename, "rU") as source_file:
        source_code = source_file.read()

        # Try and detect SyntaxError from missing or wrong encodings.
        if type(source_code) is not unicode and encoding == "ascii":
            try:
                _source_code = source_code.decode(encoding)
            except UnicodeDecodeError as e:
                lines = source_code.split("\n")
                so_far = 0

                for count, line in enumerate(lines):
                    so_far += len(line) + 1

                    if so_far > e.args[2]:
                        break
                else:
                    # Cannot happen, decode error implies non-empty.
                    count = -1

                wrong_byte = re.search(
                    "byte 0x([a-f0-9]{2}) in position",
                    str(e)
                ).group(1)

                SyntaxErrors.raiseSyntaxError(
                    reason       = """\
Non-ASCII character '\\x%s' in file %s on line %d, but no encoding declared; \
see http://python.org/dev/peps/pep-0263/ for details""" % (
                        wrong_byte,
                        source_filename,
                        count+1,
                    ),
                    source_ref   = SourceCodeReferences.fromFilename(
                        source_filename,
                        None
                    ).atLineNumber(count+1),
                    display_line = False
                )

    return source_code
Exemple #23
0
def _readSourceCodeFromFilename2(source_filename):
    # Detect the encoding.
    with open(source_filename, "rU") as source_file:
        encoding = _detectEncoding2(source_file)

        source_code = source_file.read()

        # Try and detect SyntaxError from missing or wrong encodings.
        if type(source_code) is not unicode and encoding == "ascii":
            try:
                _source_code = source_code.decode(encoding)
            except UnicodeDecodeError as e:
                lines = source_code.split('\n')
                so_far = 0

                for count, line in enumerate(lines):
                    so_far += len(line) + 1

                    if so_far > e.args[2]:
                        break
                else:
                    # Cannot happen, decode error implies non-empty.
                    count = -1

                wrong_byte = re.search(
                    "byte 0x([a-f0-9]{2}) in position",
                    str(e)
                ).group(1)

                SyntaxErrors.raiseSyntaxError(
                    reason       = """\
Non-ASCII character '\\x%s' in file %s on line %d, but no encoding declared; \
see http://python.org/dev/peps/pep-0263/ for details""" % (
                        wrong_byte,
                        source_filename,
                        count+1,
                    ),
                    source_ref   = SourceCodeReferences.fromFilename(
                        source_filename,
                        None
                    ).atLineNumber(count+1),
                    display_line = False
                )

    return source_code
Exemple #24
0
def handleNonlocalDeclarationNode(provider, node, source_ref):
    # The source reference of the nonlocal really doesn't matter, pylint: disable=W0613

    # Need to catch the error of declaring a parameter variable as global ourselves
    # here. The AST parsing doesn't catch it, but we can do it here.
    parameters = provider.getParameters()

    for variable_name in node.names:
        if variable_name in parameters.getParameterNames():
            SyntaxErrors.raiseSyntaxError(
                reason="name '%s' is parameter and nonlocal" % (variable_name),
                source_ref=None if Options.isFullCompat() else source_ref,
                display_file=not Options.isFullCompat(),
                display_line=not Options.isFullCompat())

    provider.addNonlocalsDeclaration(node.names, source_ref)

    return None
Exemple #25
0
    def onEnterNode(self, node):
        assert python_version < 300

        if node.isStatementDelVariable():
            variable = node.getTargetVariableRef().getVariable()

            if variable.isSharedLogically():
                SyntaxErrors.raiseSyntaxError(
                    reason       = """\
can not delete variable '%s' referenced in nested scope""" % (
                       variable.getName()
                    ),
                    source_ref   = (
                        None if isFullCompat() else node.getSourceReference()
                    ),
                    display_file = not isFullCompat(),
                    display_line = not isFullCompat()
                )
Exemple #26
0
def enableFutureFeature(object_name, future_spec, source_ref):
    if object_name == "unicode_literals":
        future_spec.enableUnicodeLiterals()
    elif object_name == "absolute_import":
        future_spec.enableAbsoluteImport()
    elif object_name == "division":
        future_spec.enableFutureDivision()
    elif object_name == "print_function":
        future_spec.enableFuturePrint()
    elif object_name == "barry_as_FLUFL" and Utils.python_version >= 300:
        future_spec.enableBarry()
    elif object_name == "braces":
        SyntaxErrors.raiseSyntaxError("not a chance", source_ref)
    elif object_name in ("nested_scopes", "generators", "with_statement"):
        # These are enabled in all cases already.
        pass
    else:
        SyntaxErrors.raiseSyntaxError(
            "future feature %s is not defined" % object_name, source_ref)
Exemple #27
0
def _readSourceCodeFromFilename3( source_filename ):
    source_code = open( source_filename, "rb" ).read()

    if source_code.startswith( b'\xef\xbb\xbf' ):
        return source_code[3:]

    new_line = source_code.find( b"\n" )

    if new_line is not -1:
        line = source_code[ : new_line ]

        line_match = re.search( b"coding[:=]\s*([-\w.]+)", line )

        if line_match:
            encoding = line_match.group(1).decode( "ascii" )

            # Detect encoding problem, as decode won't raise the compatible thing.
            try:
                import codecs
                codecs.lookup( encoding )
            except LookupError:
                SyntaxErrors.raiseSyntaxError(
                    reason       = "unknown encoding: %s" % encoding,
                    source_ref   = SourceCodeReferences.fromFilename( source_filename, None ),
                    display_line = False
                )

            return source_code[ new_line + 1 : ].decode( encoding )

        new_line = source_code.find( b"\n", new_line+1 )

        if new_line is not -1:
            line = source_code[ : new_line ]

            line_match = re.search( b"coding[:=]\s*([-\w.]+)", line )

            if line_match:
                encoding = line_match.group(1).decode( "ascii" )

                return source_code[ new_line + 1 : ].decode( encoding )


    return source_code.decode( "utf-8" )
Exemple #28
0
def _readSourceCodeFromFilename3(source_filename):
    source_code = open(source_filename, "rb").read()

    if source_code.startswith(b'\xef\xbb\xbf'):
        return source_code[3:]

    new_line = source_code.find(b"\n")

    if new_line is not -1:
        line = source_code[:new_line]

        line_match = re.search(b"coding[:=]\s*([-\w.]+)", line)

        if line_match:
            encoding = line_match.group(1).decode("ascii")

            # Detect encoding problem, as decode won't raise the compatible thing.
            try:
                import codecs
                codecs.lookup(encoding)
            except LookupError:
                SyntaxErrors.raiseSyntaxError(
                    reason="unknown encoding: %s" % encoding,
                    source_ref=SourceCodeReferences.fromFilename(
                        source_filename, None),
                    display_line=False)

            return source_code[new_line + 1:].decode(encoding)

        new_line = source_code.find(b"\n", new_line + 1)

        if new_line is not -1:
            line = source_code[:new_line]

            line_match = re.search(b"coding[:=]\s*([-\w.]+)", line)

            if line_match:
                encoding = line_match.group(1).decode("ascii")

                return source_code[new_line + 1:].decode(encoding)

    return source_code.decode("utf-8")
Exemple #29
0
    def onLeaveNode(self, node):
        # Return statements in generators are not really that, instead they are
        # exception raises, fix that up now. Doing it right from the onset,
        # would be a bit more difficult, as the knowledge that something is a
        # generator, requires a second pass.
        if node.isStatementReturn() and \
           node.getParentVariableProvider().isGenerator():
            return_value = node.getExpression()

            if python_version < 330:
                if not return_value.isExpressionConstantRef() or \
                   return_value.getConstant() is not None:
                    SyntaxErrors.raiseSyntaxError(
                        "'return' with argument inside generator",
                        source_ref=node.getSourceReference(),
                    )

            node.replaceWith(
                StatementGeneratorReturn(expression=return_value,
                                         source_ref=node.getSourceReference()))
Exemple #30
0
def handleGlobalDeclarationNode( provider, node, source_ref ):
    # The source reference of the global really doesn't matter, pylint: disable=W0613

    # On the module level, there is nothing to do.
    if provider.isPythonModule():
        return None

    # Need to catch the error of declaring a parameter variable as global ourselves
    # here. The AST parsing doesn't catch it.
    try:
        parameters = provider.getParameters()

        for variable_name in node.names:
            if variable_name in parameters.getParameterNames():
                SyntaxErrors.raiseSyntaxError(
                    reason     = "name '%s' is %s and global" % (
                        variable_name,
                        "local" if Utils.python_version < 300 else "parameter"
                    ),
                    source_ref = provider.getSourceReference()
                )
    except AttributeError:
        pass

    module = provider.getParentModule()

    for variable_name in node.names:
        module_variable = module.getVariableForAssignment(
            variable_name = variable_name
        )

        closure_variable = provider.addClosureVariable(
            variable         = module_variable,
            global_statement = True
        )

        provider.registerProvidedVariable(
            variable = closure_variable
        )

    return None
Exemple #31
0
    def _attachVariable(node, provider):
        # print "Late reference", node.getVariableName(), "for", provider, "caused at", node, "of", node.getParent()

        variable_name = node.getVariableName()

        was_taken = provider.hasTakenVariable(variable_name)

        variable = provider.getVariableForReference(
            variable_name = variable_name
        )

        node.setVariable(
            variable
        )

        # Need to catch functions with "exec" and closure variables not allowed.
        if python_version < 300 and \
           not was_taken and \
           provider.isExpressionFunctionBody() and \
           variable.getOwner() is not provider:
            parent_provider = provider.getParentVariableProvider()

            while parent_provider.isExpressionFunctionBody() and \
                  parent_provider.isClassDictCreation():
                parent_provider = parent_provider.getParentVariableProvider()

            if parent_provider.isExpressionFunctionBody() and \
               parent_provider.isUnqualifiedExec():
                SyntaxErrors.raiseSyntaxError(
                    reason       = PythonVersions.\
                                     getErrorMessageExecWithNestedFunction() % \
                                     parent_provider.getName(),
                    source_ref   = parent_provider.getExecSourceRef(),
                    col_offset   = None,
                    display_file = True,
                    display_line = True,
                    source_line  = None
                )
Exemple #32
0
def buildYieldNode( provider, node, source_ref ):
    if provider.isPythonModule():
        SyntaxErrors.raiseSyntaxError(
            "'yield' outside function",
            source_ref,
            None if Utils.python_version < 300 else node.col_offset
        )

    provider.markAsGenerator()

    if node.value is not None:
        return ExpressionYield(
            expression = buildNode( provider, node.value, source_ref ),
            source_ref = source_ref
        )
    else:
        return ExpressionYield(
            expression = ExpressionConstantRef(
                constant   = None,
                source_ref = source_ref
            ),
            source_ref = source_ref
        )
    def onLeaveNode(self, node):
        # Return statements in generators are not really that, instead they are
        # exception raises, fix that up now. Doing it right from the onset,
        # would be a bit more difficult, as the knowledge that something is a
        # generator, requires a second pass.
        if node.isStatementReturn() and \
           node.getParentVariableProvider().isGenerator():
            return_value = node.getExpression()

            if python_version < 330:
                if not return_value.isExpressionConstantRef() or \
                   return_value.getConstant() is not None:
                    SyntaxErrors.raiseSyntaxError(
                        "'return' with argument inside generator",
                        source_ref   = node.getSourceReference(),
                    )

            node.replaceWith(
                StatementGeneratorReturn(
                    expression  = return_value,
                    source_ref  = node.getSourceReference()
                )
            )
Exemple #34
0
def handleNonlocalDeclarationNode(provider, node, source_ref):
    # Need to catch the error of declaring a parameter variable as global
    # ourselves here. The AST parsing doesn't catch it, but we can do it here.
    parameters = provider.getParameters()

    for variable_name in node.names:
        if variable_name in parameters.getParameterNames():
            SyntaxErrors.raiseSyntaxError(
                reason       = "name '%s' is parameter and nonlocal" % (
                    variable_name
                ),
                source_ref   = None
                                 if Options.isFullCompat() and \
                                 Utils.python_version < 340 else
                               source_ref,
                display_file = not Options.isFullCompat() or \
                               Utils.python_version >= 340,
                display_line = not Options.isFullCompat() or \
                               Utils.python_version >= 340
            )

    provider.addNonlocalsDeclaration(node.names, source_ref)

    return None
    def _attachVariable(self, node, provider):
        # print "Late reference", node.getVariableName(), "for", provider, "caused at", node, "of", node.getParent()

        variable = provider.getVariableForReference(
            variable_name = node.getVariableName()
        )

        node.setVariable(
            variable
        )

        # Need to catch functions with "exec" not allowed.
        if python_version < 300 and \
           provider.isExpressionFunctionBody() and \
           variable.isReference() and \
             (not variable.isModuleVariableReference() or \
              not variable.isFromGlobalStatement() ):

            parent_provider = provider.getParentVariableProvider()

            while parent_provider.isExpressionFunctionBody() and \
                  parent_provider.isClassDictCreation():
                parent_provider = parent_provider.getParentVariableProvider()

            if parent_provider.isExpressionFunctionBody() and \
               parent_provider.isUnqualifiedExec():
                SyntaxErrors.raiseSyntaxError(
                    reason       = """\
unqualified exec is not allowed in function '%s' it \
contains a nested function with free variables""" % parent_provider.getName(),
                    source_ref   = parent_provider.getExecSourceRef(),
                    col_offset   = None,
                    display_file = True,
                    display_line = True,
                    source_line  = None
                )
Exemple #36
0
    def _handleNonLocal(self, node):
        # Take closure variables for non-local declarations.

        for non_local_names, source_ref in node.getNonlocalDeclarations():
            for non_local_name in non_local_names:
                variable = node.getClosureVariable(
                    variable_name=non_local_name)

                node.registerProvidedVariable(variable)

                if variable.isModuleVariableReference():
                    SyntaxErrors.raiseSyntaxError(
                        "no binding for nonlocal '%s' found" % (
                            non_local_name
                        ),
                        source_ref   = None
                                         if isFullCompat() and \
                                         python_version < 340 else
                                       source_ref,
                        display_file = not isFullCompat() or \
                                       python_version >= 340,
                        display_line = not isFullCompat() or \
                                       python_version >= 340
                    )
Exemple #37
0
def enableFutureFeature( object_name, future_spec, source_ref ):
    if object_name == "unicode_literals":
        future_spec.enableUnicodeLiterals()
    elif object_name == "absolute_import":
        future_spec.enableAbsoluteImport()
    elif object_name == "division":
        future_spec.enableFutureDivision()
    elif object_name == "print_function":
        future_spec.enableFuturePrint()
    elif object_name == "barry_as_FLUFL" and Utils.python_version >= 300:
        future_spec.enableBarry()
    elif object_name == "braces":
        SyntaxErrors.raiseSyntaxError(
            "not a chance",
            source_ref
        )
    elif object_name in ( "nested_scopes", "generators", "with_statement" ):
        # These are enabled in all cases already.
        pass
    else:
        SyntaxErrors.raiseSyntaxError(
            "future feature %s is not defined" % object_name,
            source_ref
        )
Exemple #38
0
    def onEnterNode( self, node ):
        if node.isExpressionTargetVariableRef():
            if node.getVariable() is None:
                variable_name = node.getVariableName()
                provider = node.getParentVariableProvider()

                variable = provider.getVariableForAssignment(
                    variable_name = variable_name
                )

                # Inside an exec, we need to ignore global declarations that are
                # not ours, so we replace it with ours, unless it came from an
                # 'global' declaration inside the exec
                if node.source_ref.isExecReference() and not provider.isPythonModule():
                    if variable.isModuleVariableReference() and not variable.isFromExecStatement():
                        variable = provider.providing[ variable_name ] = provider.createProvidedVariable(
                            variable_name = variable_name
                        )

                node.setVariable( variable )
        elif node.isExpressionVariableRef():
            if node.getVariable() is None:
                provider = node.getParentVariableProvider()

                if provider.isEarlyClosure():
                    node.setVariable(
                        provider.getVariableForReference(
                            variable_name = node.getVariableName()
                        )
                    )
        elif node.isExpressionTempVariableRef():
            if node.getVariable().getOwner().getParentVariableProvider() != node.getParentVariableProvider():
                node.setVariable(
                    node.getParentVariableProvider().addClosureVariable( node.getVariable() )
                )

                assert node.getVariable().isClosureReference(), node.getVariable()
        elif python_version >= 300 and node.isExpressionFunctionBody():
            # Take closure variables for non-local declarations.

            for non_local_names, source_ref in node.getNonlocalDeclarations():
                for non_local_name in non_local_names:
                    # print( "nonlocal reference from", node, "to name", non_local_name )

                    variable = node.getClosureVariable(
                        variable_name = non_local_name
                    )

                    node.registerProvidedVariable( variable )

                    if variable.isModuleVariableReference():
                        SyntaxErrors.raiseSyntaxError(
                            "no binding for nonlocal '%s' found" % (
                                non_local_name
                            ),
                            source_ref   = None if isFullCompat() else source_ref,
                            display_file = not isFullCompat(),
                            display_line = not isFullCompat()
                        )
        # Attribute access of names of class functions should be mangled, if they start
        # with "__", but do not end in "__" as well.
        elif node.isExpressionAttributeLookup() or node.isStatementAssignmentAttribute() or \
             node.isStatementDelAttribute():
            attribute_name = node.getAttributeName()

            if attribute_name.startswith( "__" ) and not attribute_name.endswith( "__" ):
                seen_function = False

                current = node

                while True:
                    current = current.getParentVariableProvider()

                    if current.isPythonModule():
                        break

                    assert current.isExpressionFunctionBody()

                    if current.isClassDictCreation():
                        if seen_function:
                            node.setAttributeName( "_" + current.getName() + attribute_name )

                        break
                    else:
                        seen_function = True
        # Check if continue and break are properly in loops. If not, raise a syntax error.
        elif node.isStatementBreakLoop() or node.isStatementContinueLoop():
            current = node

            while True:
                if current.isPythonModule() or current.isExpressionFunctionBody():
                    if node.isStatementContinueLoop():
                        message = "'continue' not properly in loop"
                        col_offset   = 16 if python_version >= 300 else None
                        display_line = True
                        source_line  = None
                    else:
                        message = "'break' outside loop"

                        if isFullCompat():
                            col_offset   = 2 if python_version >= 300 else None
                            display_line = True
                            source_line  = "" if python_version >= 300 else None
                        else:
                            col_offset   = 13
                            display_line = True
                            source_line  = None

                    source_ref = node.getSourceReference()
                    # source_ref.line += 1

                    SyntaxErrors.raiseSyntaxError(
                        message,
                        source_ref   = node.getSourceReference(),
                        col_offset   = col_offset,
                        display_line = display_line,
                        source_line  = source_line
                    )

                current = current.getParent()

                if current.isStatementLoop():
                    break
Exemple #39
0
def handleGlobalDeclarationNode(provider, node, source_ref):

    # On the module level, there is nothing to do. TODO: Probably a warning
    # would be warranted.
    if provider.isPythonModule():
        return None

    # Need to catch the error of declaring a parameter variable as global
    # ourselves here. The AST parsing doesn't catch it, so we check here.
    try:
        parameters = provider.getParameters()

        for variable_name in node.names:
            if variable_name in parameters.getParameterNames():
                SyntaxErrors.raiseSyntaxError(
                    reason     = "name '%s' is %s and global" % (
                        variable_name,
                        "local"
                          if Utils.python_version < 300 else
                        "parameter"
                    ),
                    source_ref = (
                        source_ref
                          if not Options.isFullCompat() or \
                             Utils.python_version >= 340 else
                        provider.getSourceReference()
                    )
                )
    except AttributeError:
        pass

    # The module the "global" statement refers to.
    module = provider.getParentModule()

    # Can give multiple names.
    for variable_name in node.names:
        closure_variable = None

        # Re-use already taken global variables, in order to avoid creating yet
        # another instance, esp. as the markups could then potentially not be
        # shared.
        if provider.hasTakenVariable(variable_name):
            closure_variable = provider.getTakenVariable(variable_name)

            # Only global variables count. Could have a closure reference to
            # a location of a parent function here.
            if not closure_variable.isModuleVariable():
                closure_variable = None

        if closure_variable is None:
            module_variable = module.getVariableForAssignment(
                variable_name = variable_name
            )

            closure_variable = provider.addClosureVariable(
                variable = module_variable
            )

        assert closure_variable.isModuleVariable()

        provider.registerProvidedVariable(
            variable = closure_variable
        )

    return None
def buildTryExceptionNode(provider, node, source_ref):
    # Try/except nodes. Re-formulated as described in the developer
    # manual. Exception handlers made the assignment to variables explicit. Same
    # for the "del" as done for Python3. Also catches always work a tuple of
    # exception types and hides away that they may be built or not.

    # Many variables, due to the re-formulation that is going on here, which
    # just has the complexity, pylint: disable=R0914

    handlers = []

    for handler in node.handlers:
        exception_expression, exception_assign, exception_block = (
            handler.type,
            handler.name,
            handler.body
        )

        statements = [
            buildAssignmentStatements(
                provider   = provider,
                node       = exception_assign,
                allow_none = True,
                source     = ExpressionCaughtExceptionValueRef(
                    source_ref = source_ref.atInternal()
                ),
                source_ref = source_ref.atInternal()
            ),
            buildStatementsNode(
                provider   = provider,
                nodes      = exception_block,
                source_ref = source_ref
            )
        ]

        if Utils.python_version >= 300:
            target_info = decodeAssignTarget(
                provider   = provider,
                node       = exception_assign,
                source_ref = source_ref,
                allow_none = True
            )

            if target_info is not None:
                kind, detail = target_info

                assert kind == "Name", kind
                kind = "Name_Exception"

                statements.append(
                    buildDeleteStatementFromDecoded(
                        kind       = kind,
                        detail     = detail,
                        source_ref = source_ref
                    )
                )

        handler_body = makeStatementsSequence(
            statements = statements,
            allow_none = True,
            source_ref = source_ref
        )

        exception_types = buildNode(
            provider   = provider,
            node       = exception_expression,
            source_ref = source_ref,
            allow_none = True
        )

        # The exception types should be a tuple, so as to be most general.
        if exception_types is None:
            exception_types = ()

            if handler is not node.handlers[-1]:
                SyntaxErrors.raiseSyntaxError(
                    reason    = "default 'except:' must be last",
                    source_ref = source_ref.atLineNumber(
                        handler.lineno-1
                          if Options.isFullCompat() else
                        handler.lineno
                    )
                )
        elif exception_types.isExpressionMakeSequence():
            exception_types = exception_types.getElements()
        else:
            exception_types = (exception_types,)

        handlers.append(
            StatementExceptHandler(
                exception_types = exception_types,
                body            = handler_body,
                source_ref      = source_ref
            )
        )

    tried = buildStatementsNode(
        provider   = provider,
        nodes      = node.body,
        source_ref = source_ref
    )

    no_raise = buildStatementsNode(
        provider   = provider,
        nodes      = node.orelse,
        source_ref = source_ref
    )

    if no_raise is None:
        return StatementTryExcept(
            handlers   = handlers,
            tried      = tried,
            source_ref = source_ref
        )
    else:
        return makeTryExceptNoRaise(
            provider   = provider,
            temp_scope = provider.allocateTempScope("try_except"),
            handlers   = handlers,
            tried      = tried,
            no_raise   = no_raise,
            source_ref = source_ref
        )
Exemple #41
0
def buildParseTree( provider, source_code, source_ref, is_module,
                    is_main ):
    # Workaround: ast.parse cannot cope with some situations where a file is not
    # terminated by a new line.
    if not source_code.endswith( "\n" ):
        source_code = source_code + "\n"

    body = ast.parse( source_code, source_ref.getFilename() )
    assert getKind( body ) == "Module"

    line_offset = source_ref.getLineNumber() - 1

    if line_offset > 0:
        for created_node in ast.walk( body ):
            if hasattr( created_node, "lineno" ):
                created_node.lineno += line_offset

    body, doc = extractDocFromBody( body )

    result = buildStatementsNode(
        provider   = provider,
        nodes      = body,
        source_ref = source_ref
    )

    # Check if a __future__ imports really were at the beginning of the file.
    for node in body:
        if node in _future_import_nodes:
            _future_import_nodes.remove( node )
        else:
            if _future_import_nodes:
                SyntaxErrors.raiseSyntaxError(
                    reason     = """\
from __future__ imports must occur at the beginning of the file""",
                    col_offset = 1
                      if Utils.python_version >= 300 or \
                      not Options.isFullCompat() else
                    None,
                    source_ref = _future_import_nodes[0].source_ref
                )

    internal_source_ref = source_ref.atInternal()

    statements = []

    if is_module:
        # Add import of "site" module of main programs visibly in the node tree,
        # so recursion and optimization can pick it up, checking its effects.
        if is_main and not sys.flags.no_site:
            statements.append(
                StatementExpressionOnly(
                    expression = ExpressionImportModule(
                        module_name    = "site",
                        import_list    = (),
                        level          = 0,
                        source_ref     = source_ref,
                    ),
                    source_ref  = source_ref
                )
            )

        statements.append(
            StatementAssignmentVariable(
                variable_ref = ExpressionTargetVariableRef(
                    variable_name = "__doc__",
                    source_ref    = internal_source_ref
                ),
                source       = ExpressionConstantRef(
                    constant      = doc,
                    source_ref    = internal_source_ref,
                    user_provided = True
                ),
                source_ref   = internal_source_ref
            )
        )

        statements.append(
            StatementAssignmentVariable(
                variable_ref = ExpressionTargetVariableRef(
                    variable_name = "__file__",
                    source_ref    = internal_source_ref
                ),
                source       = ExpressionConstantRef(
                    constant      = source_ref.getFilename(),
                    source_ref    = internal_source_ref,
                    user_provided = True
                ),
                source_ref   = internal_source_ref
            )
        )

        if provider.isPythonPackage():
            # TODO: __package__ is not set here, but automatically, which makes
            # it invisible though
            statements.append(
                StatementAssignmentVariable(
                    variable_ref = ExpressionTargetVariableRef(
                        variable_name = "__path__",
                        source_ref    = internal_source_ref
                    ),
                    source       = ExpressionConstantRef(
                        constant      = [
                            Utils.dirname( source_ref.getFilename() )
                        ],
                        source_ref    = internal_source_ref,
                        user_provided = True
                    ),
                    source_ref   = internal_source_ref
                )
            )

    if Utils.python_version >= 300:
        statements.append(
            StatementAssignmentVariable(
                variable_ref = ExpressionTargetVariableRef(
                    variable_name = "__cached__",
                    source_ref    = internal_source_ref
                ),
                source       = ExpressionConstantRef(
                    constant      = None,
                    source_ref    = internal_source_ref,
                    user_provided = True
                ),
                source_ref   = internal_source_ref
            )
        )


    if Utils.python_version >= 330:
        # For Python3.3, it's set for both packages and non-packages.
        statements.append(
            StatementAssignmentVariable(
                variable_ref = ExpressionTargetVariableRef(
                    variable_name = "__package__",
                    source_ref    = internal_source_ref
                ),
                source       = ExpressionConstantRef(
                    constant      = provider.getFullName()
                                      if provider.isPythonPackage() else
                                    provider.getPackage(),
                    source_ref    = internal_source_ref,
                    user_provided = True
                ),
                source_ref   = internal_source_ref
            )
        )

    if Utils.python_version >= 330 and not provider.isMainModule():
        # Set initialzing at the beginning to True
        statements.append(
            StatementAssignmentVariable(
                variable_ref = ExpressionTargetVariableRef(
                    variable_name = "__initializing__",
                    source_ref    = internal_source_ref
                ),
                source       = ExpressionConstantRef(
                    constant      = True,
                    source_ref    = internal_source_ref,
                    user_provided = True
                ),
                source_ref   = internal_source_ref
            )
        )

    # Now the module body if there is any at all.
    if result is not None:
        statements.extend( result.getStatements() )

    if Utils.python_version >= 330 and not provider.isMainModule():
        # Set initialzing at the beginning to True
        statements.append(
            StatementAssignmentVariable(
                variable_ref = ExpressionTargetVariableRef(
                    variable_name = "__initializing__",
                    source_ref    = internal_source_ref
                ),
                source       = ExpressionConstantRef(
                    constant      = False,
                    source_ref    = internal_source_ref,
                    user_provided = True
                ),
                source_ref   = internal_source_ref
            )
        )


    if is_module:
        return makeModuleFrame(
            module = provider,
            statements = statements,
            source_ref = source_ref
        )
    else:
        assert False
Exemple #42
0
def handleGlobalDeclarationNode(provider, node, source_ref):

    # On the module level, there is nothing to do. TODO: Probably a warning
    # would be warranted.
    if provider.isPythonModule():
        return None

    # Need to catch the error of declaring a parameter variable as global
    # ourselves here. The AST parsing doesn't catch it, so we check here.
    try:
        parameters = provider.getParameters()

        for variable_name in node.names:
            if variable_name in parameters.getParameterNames():
                SyntaxErrors.raiseSyntaxError(
                    reason     = "name '%s' is %s and global" % (
                        variable_name,
                        "local"
                          if Utils.python_version < 300 else
                        "parameter"
                    ),
                    source_ref = (
                        source_ref
                          if not Options.isFullCompat() or \
                             Utils.python_version >= 340 else
                        provider.getSourceReference()
                    )
                )
    except AttributeError:
        pass

    # The module the "global" statement refers to.
    module = provider.getParentModule()

    # Can give multiple names.
    for variable_name in node.names:
        closure_variable = None

        # Re-use already taken global variables, in order to avoid creating yet
        # another instance, esp. as the indications could then potentially not
        # be shared.
        if provider.hasTakenVariable(variable_name):
            closure_variable = provider.getTakenVariable(variable_name)

            # Only global variables count. Could have a closure reference to
            # a location of a parent function here.
            if not closure_variable.isModuleVariable():
                closure_variable = None

        if closure_variable is None:
            module_variable = module.getVariableForAssignment(
                variable_name = variable_name
            )

            closure_variable = provider.addClosureVariable(
                variable = module_variable
            )

        assert closure_variable.isModuleVariable()

        if Utils.python_version < 340 and \
           provider.isClassDictCreation() and \
           closure_variable.getName() == "__class__":
            SyntaxErrors.raiseSyntaxError(
                reason     = "cannot make __class__ global",
                source_ref = source_ref
            )

        provider.registerProvidedVariable(
            variable = closure_variable
        )

    return None
Exemple #43
0
    def onEnterNode(self, node):
        if node.isExpressionTargetVariableRef():
            if node.getVariable() is None:
                variable_name = node.getVariableName()
                provider = node.getParentVariableProvider()

                variable = provider.getVariableForAssignment(
                    variable_name = variable_name
                )

                # Inside an exec, we need to ignore global declarations that are
                # not ours, so we replace it with ours, unless it came from an
                # 'global' declaration inside the exec
                if node.source_ref.isExecReference() and not provider.isPythonModule():
                    if variable.isModuleVariableReference() and not variable.isFromExecStatement():
                        variable = provider.providing[ variable_name ] = provider.createProvidedVariable(
                            variable_name = variable_name
                        )

                node.setVariable( variable )
        elif node.isExpressionVariableRef():
            if node.getVariable() is None:
                provider = node.getParentVariableProvider()

                if provider.isEarlyClosure():
                    node.setVariable(
                        provider.getVariableForReference(
                            variable_name = node.getVariableName()
                        )
                    )
        elif node.isExpressionTempVariableRef():
            if node.getVariable().getOwner() != node.getParentVariableProvider():
                node.setVariable(
                    node.getParentVariableProvider().addClosureVariable(
                        node.getVariable()
                    )
                )

                assert node.getVariable().isClosureReference(), node.getVariable()
        elif python_version >= 300 and node.isExpressionFunctionBody():
            # Take closure variables for non-local declarations.

            for non_local_names, source_ref in node.getNonlocalDeclarations():
                for non_local_name in non_local_names:
                    # print( "nonlocal reference from", node, "to name", non_local_name )

                    variable = node.getClosureVariable(
                        variable_name = non_local_name
                    )

                    node.registerProvidedVariable( variable )

                    if variable.isModuleVariableReference():
                        SyntaxErrors.raiseSyntaxError(
                            "no binding for nonlocal '%s' found" % (
                                non_local_name
                            ),
                            source_ref   = None if isFullCompat() else source_ref,
                            display_file = not isFullCompat(),
                            display_line = not isFullCompat()
                        )
        # Attribute access of names of class functions should be mangled, if
        # they start with "__", but do not end in "__" as well.
        elif node.isExpressionAttributeLookup() or node.isStatementAssignmentAttribute() or \
             node.isStatementDelAttribute():
            attribute_name = node.getAttributeName()

            if attribute_name.startswith( "__" ) and not attribute_name.endswith( "__" ):
                seen_function = False

                current = node

                while True:
                    current = current.getParentVariableProvider()

                    if current.isPythonModule():
                        break

                    assert current.isExpressionFunctionBody()

                    if current.isClassDictCreation():
                        if seen_function:
                            node.setAttributeName(
                                "_%s%s" % (
                                    current.getName().lstrip("_"),
                                    attribute_name
                                )
                            )

                        break
                    else:
                        seen_function = True
        # Check if continue and break are properly in loops. If not, raise a
        # syntax error.
        elif node.isStatementBreakLoop() or node.isStatementContinueLoop():
            current = node

            while True:
                if current.isPythonModule() or current.isExpressionFunctionBody():
                    if node.isStatementContinueLoop():
                        message = "'continue' not properly in loop"
                        col_offset   = 16 if python_version >= 300 else None
                        display_line = True
                        source_line  = None
                    else:
                        message = "'break' outside loop"

                        if isFullCompat():
                            col_offset   = 2 if python_version >= 300 else None
                            display_line = True
                            source_line  = "" if python_version >= 300 else None
                        else:
                            col_offset   = 13
                            display_line = True
                            source_line  = None

                    source_ref = node.getSourceReference()
                    # source_ref.line += 1

                    SyntaxErrors.raiseSyntaxError(
                        message,
                        source_ref   = node.getSourceReference(),
                        col_offset   = col_offset,
                        display_line = display_line,
                        source_line  = source_line
                    )

                current = current.getParent()

                if current.isStatementLoop():
                    break
def buildImportFromNode(provider, node, source_ref):
    # "from .. import .." statements. This may trigger a star import, or
    # multiple names being looked up from the given module variable name.

    module_name = node.module if node.module is not None else ""
    level = node.level

    # Importing from "__future__" module may enable flags to the parser,
    # that we need to know.
    if module_name == "__future__":
        # Future imports we see are all legal, and known to work.

        if not provider.isPythonModule():
            SyntaxErrors.raiseSyntaxError(
                reason     = """\
from __future__ imports must occur at the beginning of the file""",
                col_offset = 8
                  if Utils.python_version >= 300 or \
                  not Options.isFullCompat()
                else None,
                source_ref = source_ref
            )

        for import_desc in node.names:
            object_name, _local_name = import_desc.name, import_desc.asname

            enableFutureFeature(object_name=object_name,
                                future_spec=source_ref.getFutureSpec(),
                                source_ref=source_ref)

        # Remember it for checks to be applied once module is complete.
        node.source_ref = source_ref
        _future_import_nodes.append(node)

    target_names = []
    import_names = []

    for import_desc in node.names:
        object_name, local_name = import_desc.name, import_desc.asname

        if object_name == '*':
            target_names.append(None)
        else:
            target_names.append(
                local_name if local_name is not None else object_name)

        import_names.append(object_name)

    if None in target_names:
        # More than "*" is a syntax error in Python, need not care about this at
        # all, it's only allowed value for import list in  this case.
        assert target_names == [None]

        # Python3 made this a syntax error unfortunately.
        if not provider.isPythonModule() and Utils.python_version >= 300:
            SyntaxErrors.raiseSyntaxError(
                "import * only allowed at module level",
                provider.getSourceReference())

        if provider.isExpressionFunctionBody():
            provider.markAsStarImportContaining()

        return StatementImportStar(module_import=ExpressionImportModule(
            module_name=module_name,
            import_list=('*', ),
            level=level,
            source_ref=source_ref),
                                   source_ref=source_ref)
    else:
        # Make __future__ imports "hard" immediately, they cannot be any other
        # way.
        def makeImportName(import_name):
            if module_name == "__future__":
                return ExpressionImportModuleHard(module_name="__future__",
                                                  import_name=import_name,
                                                  source_ref=source_ref)
            else:
                return ExpressionImportName(module=ExpressionImportModule(
                    module_name=module_name,
                    import_list=tuple(import_names),
                    level=level,
                    source_ref=source_ref),
                                            import_name=import_name,
                                            source_ref=source_ref)

        import_nodes = []

        for target_name, import_name in zip(target_names, import_names):
            import_nodes.append(
                StatementAssignmentVariable(
                    variable_ref=ExpressionTargetVariableRef(
                        variable_name=mangleName(target_name, provider),
                        source_ref=source_ref),
                    source=makeImportName(import_name=import_name, ),
                    source_ref=source_ref))

        # Note: Each import is sequential. It can succeed, and the failure of a
        # later one is not changing one. We can therefore have a sequence of
        # imports that only import one thing therefore.
        return StatementsSequence(statements=import_nodes,
                                  source_ref=source_ref)
Exemple #45
0
def buildParseTree( provider, source_code, source_ref, is_module ):
    # Workaround: ast.parse cannot cope with some situations where a file is not terminated
    # by a new line.
    if not source_code.endswith( "\n" ):
        source_code = source_code + "\n"

    body = ast.parse( source_code, source_ref.getFilename() )
    assert getKind( body ) == "Module"

    line_offset = source_ref.getLineNumber() - 1

    if line_offset > 0:
        for created_node in ast.walk( body ):
            if hasattr( created_node, "lineno" ):
                created_node.lineno += line_offset

    body, doc = extractDocFromBody( body )

    result = buildStatementsNode(
        provider   = provider,
        nodes      = body,
        source_ref = source_ref,
        frame      = is_module
    )

    # Check if a __future__ imports really were at the beginning of the file.
    for node in body:
        if node in _future_import_nodes:
            _future_import_nodes.remove( node )
        else:
            if _future_import_nodes:
                SyntaxErrors.raiseSyntaxError(
                    reason     = "from __future__ imports must occur at the beginning of the file",
                    col_offset = 1 if Utils.python_version >= 300 or not Options.isFullCompat() else None,
                    source_ref = _future_import_nodes[0].source_ref
                )

    internal_source_ref = source_ref.atInternal()

    statements = []

    if is_module:
        statements.append(
            StatementAssignmentVariable(
                variable_ref = ExpressionTargetVariableRef(
                    variable_name = "__doc__",
                    source_ref    = internal_source_ref
                ),
                source       = ExpressionConstantRef(
                    constant   = doc,
                    source_ref = internal_source_ref
                ),
                source_ref   = internal_source_ref
            )
        )

        statements.append(
            StatementAssignmentVariable(
                variable_ref = ExpressionTargetVariableRef(
                    variable_name = "__file__",
                    source_ref    = internal_source_ref
                ),
                source       = ExpressionConstantRef(
                    constant   = source_ref.getFilename(),
                    source_ref = internal_source_ref
                ),
                source_ref   = internal_source_ref
            )
        )

        if provider.isPythonPackage():
            # TODO: __package__ is not set here, but automatically, which makes it invisible
            # though
            statements.append(
                StatementAssignmentVariable(
                    variable_ref = ExpressionTargetVariableRef(
                        variable_name = "__path__",
                        source_ref    = internal_source_ref
                    ),
                    source       = ExpressionConstantRef(
                        constant   = [ Utils.dirname( source_ref.getFilename() ) ],
                        source_ref = internal_source_ref
                    ),
                    source_ref   = internal_source_ref
                )
            )

    if Utils.python_version >= 300:
        statements.append(
            StatementAssignmentVariable(
                variable_ref = ExpressionTargetVariableRef(
                    variable_name = "__cached__",
                    source_ref    = internal_source_ref
                ),
                source       = ExpressionConstantRef(
                    constant   = None,
                    source_ref = internal_source_ref
                ),
                source_ref   = internal_source_ref
            )
        )


    if Utils.python_version >= 330:
        # For Python3.3, it's set for both packages and non-packages.
        statements.append(
            StatementAssignmentVariable(
                variable_ref = ExpressionTargetVariableRef(
                    variable_name = "__package__",
                    source_ref    = internal_source_ref
                ),
                source       = ExpressionConstantRef(
                    constant   = provider.getPackage(),
                    source_ref = internal_source_ref
                ),
                source_ref   = internal_source_ref
            )
        )

    if Utils.python_version >= 330 and not provider.isMainModule():
        # Set initialzing at the beginning to True
        statements.append(
            StatementAssignmentVariable(
                variable_ref = ExpressionTargetVariableRef(
                    variable_name = "__initializing__",
                    source_ref    = internal_source_ref
                ),
                source       = ExpressionConstantRef(
                    constant   = True,
                    source_ref = internal_source_ref
                ),
                source_ref   = internal_source_ref
            )
        )


    # Now the module body if there is any at all.
    if result is not None:
        statements.extend( result.getStatements() )

    if Utils.python_version >= 330 and not provider.isMainModule():
        # Set initialzing at the beginning to True
        statements.append(
            StatementAssignmentVariable(
                variable_ref = ExpressionTargetVariableRef(
                    variable_name = "__initializing__",
                    source_ref    = internal_source_ref
                ),
                source       = ExpressionConstantRef(
                    constant   = False,
                    source_ref = internal_source_ref
                ),
                source_ref   = internal_source_ref
            )
        )

    if result is None:
        result = makeStatementsSequence(
            statements = statements,
            source_ref = internal_source_ref,
            allow_none = False
        )
    else:
        result.setStatements( statements )

    return result
    def onEnterNode(self, node):
        # Mighty complex code with lots of branches and statements, but it
        # couldn't be less without making it more difficult.
        # pylint: disable=R0912,R0915

        if node.isExpressionTargetVariableRef():
            provider = node.getParentVariableProvider()

            if node.getVariable() is None:
                variable_name = node.getVariableName()

                variable = provider.getVariableForAssignment(
                    variable_name=variable_name)

                node.setVariable(variable)

            addVariableUsage(node.getVariable(), provider)
        elif node.isExpressionTargetTempVariableRef():
            provider = node.getParentVariableProvider()

            addVariableUsage(node.getVariable(), provider)
        elif node.isExpressionVariableRef():
            if node.getVariable() is None:
                provider = node.getParentVariableProvider()

                if provider.isEarlyClosure():
                    variable = provider.getVariableForReference(
                        variable_name=node.getVariableName())

                    # Python3.4 version respects closure variables taken can be
                    # overridden by writes to locals. It should be done for
                    # globals too, on all versions, but for Python2 the locals
                    # dictionary is avoided unless "exec" appears, so it's not
                    # done.
                    if variable.getOwner() is not provider:
                        if python_version >= 340 or \
                           (python_version >= 300 and \
                            variable.isModuleVariable()):
                            variable = Variables.MaybeLocalVariable(
                                owner=provider, maybe_variable=variable)

                    node.setVariable(variable)
        elif node.isExpressionTempVariableRef():
            if node.getVariable().getOwner() != node.getParentVariableProvider(
            ):
                node.setVariable(
                    node.getParentVariableProvider().addClosureVariable(
                        node.getVariable()))
        elif node.isExpressionFunctionBody():
            if python_version >= 300:
                self._handleNonLocal(node)

            for variable in node.getParameters().getAllVariables():
                addVariableUsage(variable, node)

            # Python3.4 allows for class declarations to be made global, even
            # after they were declared, so we need to fix this up.
            if python_version >= 340:
                self._handleQualnameSetup(node)
        # Attribute access of names of class functions should be mangled, if
        # they start with "__", but do not end in "__" as well.
        elif node.isExpressionAttributeLookup() or \
             node.isStatementAssignmentAttribute() or \
             node.isStatementDelAttribute():
            attribute_name = node.getAttributeName()

            if attribute_name.startswith("__") and \
               not attribute_name.endswith("__"):
                seen_function = False

                current = node

                while True:
                    current = current.getParentVariableProvider()

                    if current.isPythonModule():
                        break

                    assert current.isExpressionFunctionBody()

                    if current.isClassDictCreation():
                        if seen_function:
                            node.setAttributeName(
                                "_%s%s" % (current.getName().lstrip("_"),
                                           attribute_name))

                        break
                    else:
                        seen_function = True
        # Check if continue and break are properly in loops. If not, raise a
        # syntax error.
        elif node.isStatementBreakLoop() or node.isStatementContinueLoop():
            current = node

            while True:
                if current.isPythonModule() or \
                   current.isExpressionFunctionBody():
                    if node.isStatementContinueLoop():
                        message = "'continue' not properly in loop"
                        col_offset = 16 if python_version >= 300 else None
                        display_line = True
                        source_line = None
                    else:
                        message = "'break' outside loop"

                        if isFullCompat():
                            col_offset = 2 if python_version >= 300 else None
                            display_line = True
                            source_line = "" if python_version >= 300 else None
                        else:
                            col_offset = 13
                            display_line = True
                            source_line = None

                    SyntaxErrors.raiseSyntaxError(
                        message,
                        source_ref=node.getSourceReference(),
                        col_offset=col_offset,
                        display_line=display_line,
                        source_line=source_line)

                current = current.getParent()

                if current.isStatementLoop():
                    break
def buildTryExceptionNode(provider, node, source_ref):
    # Try/except nodes. Re-formulated as described in the developer
    # manual. Exception handlers made the assignment to variables explicit. Same
    # for the "del" as done for Python3. Also catches always work a tuple of
    # exception types and hides away that they may be built or not.

    # Many variables, due to the re-formulation that is going on here, which
    # just has the complexity, pylint: disable=R0914

    handlers = []

    for handler in node.handlers:
        exception_expression, exception_assign, exception_block = (
            handler.type, handler.name, handler.body)

        statements = [
            buildAssignmentStatements(provider=provider,
                                      node=exception_assign,
                                      allow_none=True,
                                      source=ExpressionCaughtExceptionValueRef(
                                          source_ref=source_ref.atInternal()),
                                      source_ref=source_ref.atInternal()),
            buildStatementsNode(provider=provider,
                                nodes=exception_block,
                                source_ref=source_ref)
        ]

        if Utils.python_version >= 300:
            target_info = decodeAssignTarget(provider=provider,
                                             node=exception_assign,
                                             source_ref=source_ref,
                                             allow_none=True)

            if target_info is not None:
                kind, detail = target_info

                assert kind == "Name", kind
                kind = "Name_Exception"

                statements.append(
                    buildDeleteStatementFromDecoded(kind=kind,
                                                    detail=detail,
                                                    source_ref=source_ref))

        handler_body = makeStatementsSequence(statements=statements,
                                              allow_none=True,
                                              source_ref=source_ref)

        exception_types = buildNode(provider=provider,
                                    node=exception_expression,
                                    source_ref=source_ref,
                                    allow_none=True)

        # The exception types should be a tuple, so as to be most general.
        if exception_types is None:
            exception_types = ()

            if handler is not node.handlers[-1]:
                SyntaxErrors.raiseSyntaxError(
                    reason="default 'except:' must be last",
                    source_ref=source_ref.atLineNumber(
                        handler.lineno -
                        1 if Options.isFullCompat() else handler.lineno))
        elif exception_types.isExpressionMakeSequence():
            exception_types = exception_types.getElements()
        else:
            exception_types = (exception_types, )

        handlers.append(
            StatementExceptHandler(exception_types=exception_types,
                                   body=handler_body,
                                   source_ref=source_ref))

    tried = buildStatementsNode(provider=provider,
                                nodes=node.body,
                                source_ref=source_ref)

    no_raise = buildStatementsNode(provider=provider,
                                   nodes=node.orelse,
                                   source_ref=source_ref)

    if no_raise is None:
        return StatementTryExcept(handlers=handlers,
                                  tried=tried,
                                  source_ref=source_ref)
    else:
        return makeTryExceptNoRaise(
            provider=provider,
            temp_scope=provider.allocateTempScope("try_except"),
            handlers=handlers,
            tried=tried,
            no_raise=no_raise,
            source_ref=source_ref)
Exemple #48
0
    def onEnterNode(self, node):
        # Mighty complex code with lots of branches and statements, but it
        # couldn't be less without making it more difficult.
        # pylint: disable=R0912,R0915

        if node.isExpressionTargetVariableRef():
            provider = node.getParentVariableProvider()

            if node.getVariable() is None:
                variable_name = node.getVariableName()

                variable = provider.getVariableForAssignment(
                    variable_name=variable_name)

                node.setVariable(variable)

            addVariableUsage(node.getVariable(), provider)
        elif node.isExpressionTargetTempVariableRef():
            provider = node.getParentVariableProvider()

            addVariableUsage(node.getVariable(), provider)
        elif node.isExpressionVariableRef():
            if node.getVariable() is None:
                provider = node.getParentVariableProvider()

                if provider.isEarlyClosure():
                    node.setVariable(
                        provider.getVariableForReference(
                            variable_name=node.getVariableName()))
        elif node.isExpressionTempVariableRef():
            if node.getVariable().getOwner() != node.getParentVariableProvider(
            ):
                node.setVariable(
                    node.getParentVariableProvider().addClosureVariable(
                        node.getVariable()))

                assert node.getVariable().isClosureReference(), \
                  node.getVariable()
        elif node.isExpressionFunctionBody():
            if python_version >= 300:
                self._handleNonLocal(node)

            for variable in node.getParameters().getAllVariables():
                addVariableUsage(variable, node)

        # Attribute access of names of class functions should be mangled, if
        # they start with "__", but do not end in "__" as well.
        elif node.isExpressionAttributeLookup() or \
             node.isStatementAssignmentAttribute() or \
             node.isStatementDelAttribute():
            attribute_name = node.getAttributeName()

            if attribute_name.startswith( "__" ) and \
               not attribute_name.endswith( "__" ):
                seen_function = False

                current = node

                while True:
                    current = current.getParentVariableProvider()

                    if current.isPythonModule():
                        break

                    assert current.isExpressionFunctionBody()

                    if current.isClassDictCreation():
                        if seen_function:
                            node.setAttributeName(
                                "_%s%s" % (current.getName().lstrip("_"),
                                           attribute_name))

                        break
                    else:
                        seen_function = True
        # Check if continue and break are properly in loops. If not, raise a
        # syntax error.
        elif node.isStatementBreakLoop() or node.isStatementContinueLoop():
            current = node

            while True:
                if current.isPythonModule(
                ) or current.isExpressionFunctionBody():
                    if node.isStatementContinueLoop():
                        message = "'continue' not properly in loop"
                        col_offset = 16 if python_version >= 300 else None
                        display_line = True
                        source_line = None
                    else:
                        message = "'break' outside loop"

                        if isFullCompat():
                            col_offset = 2 if python_version >= 300 else None
                            display_line = True
                            source_line = "" if python_version >= 300 else None
                        else:
                            col_offset = 13
                            display_line = True
                            source_line = None

                    source_ref = node.getSourceReference()
                    # source_ref.line += 1

                    SyntaxErrors.raiseSyntaxError(
                        message,
                        source_ref=node.getSourceReference(),
                        col_offset=col_offset,
                        display_line=display_line,
                        source_line=source_line)

                current = current.getParent()

                if current.isStatementLoop():
                    break
Exemple #49
0
def buildParseTree(provider, source_code, source_ref):
    # Workaround: ast.parse cannot cope with some situations where a file is not terminated
    # by a new line.
    if not source_code.endswith("\n"):
        source_code = source_code + "\n"

    body = ast.parse(source_code, source_ref.getFilename())
    assert getKind(body) == "Module"

    line_offset = source_ref.getLineNumber() - 1

    if line_offset > 0:
        for created_node in ast.walk(body):
            if hasattr(created_node, "lineno"):
                created_node.lineno += line_offset

    body, doc = extractDocFromBody(body)

    result = buildStatementsNode(provider=provider,
                                 nodes=body,
                                 source_ref=source_ref,
                                 frame=True)

    # Check if a __future__ imports really were at the beginning of the file.
    for node in body:
        if node in _future_import_nodes:
            _future_import_nodes.remove(node)
        else:
            if _future_import_nodes:
                SyntaxErrors.raiseSyntaxError(
                    reason=
                    "from __future__ imports must occur at the beginning of the file",
                    col_offset=1 if Utils.python_version >= 300
                    or not Options.isFullCompat() else None,
                    source_ref=_future_import_nodes[0].source_ref)

    internal_source_ref = source_ref.atInternal()

    statements = []

    statements.append(
        StatementAssignmentVariable(variable_ref=ExpressionTargetVariableRef(
            variable_name="__doc__", source_ref=internal_source_ref),
                                    source=ExpressionConstantRef(
                                        constant=doc,
                                        source_ref=internal_source_ref),
                                    source_ref=internal_source_ref))

    statements.append(
        StatementAssignmentVariable(variable_ref=ExpressionTargetVariableRef(
            variable_name="__file__", source_ref=internal_source_ref),
                                    source=ExpressionConstantRef(
                                        constant=source_ref.getFilename(),
                                        source_ref=internal_source_ref),
                                    source_ref=internal_source_ref))

    if provider.isPythonPackage():
        # TODO: __package__ is not set here, but automatically, which makes it invisible
        # though
        statements.append(
            StatementAssignmentVariable(
                variable_ref=ExpressionTargetVariableRef(
                    variable_name="__path__", source_ref=internal_source_ref),
                source=ExpressionConstantRef(
                    constant=[Utils.dirname(source_ref.getFilename())],
                    source_ref=internal_source_ref),
                source_ref=internal_source_ref))

    if Utils.python_version >= 300:
        statements.append(
            StatementAssignmentVariable(
                variable_ref=ExpressionTargetVariableRef(
                    variable_name="__cached__",
                    source_ref=internal_source_ref),
                source=ExpressionConstantRef(constant=None,
                                             source_ref=internal_source_ref),
                source_ref=internal_source_ref))

    if Utils.python_version >= 330:
        # For Python3.3, it's set for both packages and non-packages.
        statements.append(
            StatementAssignmentVariable(
                variable_ref=ExpressionTargetVariableRef(
                    variable_name="__package__",
                    source_ref=internal_source_ref),
                source=ExpressionConstantRef(constant=provider.getPackage(),
                                             source_ref=internal_source_ref),
                source_ref=internal_source_ref))

    if Utils.python_version >= 330:
        # Set initialzing at the beginning to True
        statements.append(
            StatementAssignmentVariable(
                variable_ref=ExpressionTargetVariableRef(
                    variable_name="__initializing__",
                    source_ref=internal_source_ref),
                source=ExpressionConstantRef(constant=True,
                                             source_ref=internal_source_ref),
                source_ref=internal_source_ref))

    # Now the module body if there is any at all.
    if result is not None:
        statements.extend(result.getStatements())

    if Utils.python_version >= 330:
        # Set initialzing at the beginning to True
        statements.append(
            StatementAssignmentVariable(
                variable_ref=ExpressionTargetVariableRef(
                    variable_name="__initializing__",
                    source_ref=internal_source_ref),
                source=ExpressionConstantRef(constant=False,
                                             source_ref=internal_source_ref),
                source_ref=internal_source_ref))

    if result is None:
        result = makeStatementsSequence(statements=statements,
                                        source_ref=internal_source_ref,
                                        allow_none=False)
    else:
        result.setStatements(statements)

    provider.setBody(result)

    return result
Exemple #50
0
def buildImportFromNode( provider, node, source_ref ):
    # "from .. import .." statements. This may trigger a star import, or multiple names
    # being looked up from the given module variable name.

    module_name = node.module if node.module is not None else ""
    level = node.level

    # Importing from "__future__" module may enable flags.
    if module_name == "__future__":
        if not provider.isPythonModule() and not source_ref.isExecReference():
            SyntaxErrors.raiseSyntaxError(
                reason     = "from __future__ imports must occur at the beginning of the file",
                col_offset = 8 if Utils.python_version >= 300 or not Options.isFullCompat() else None,
                source_ref = source_ref
            )


        for import_desc in node.names:
            object_name, _local_name = import_desc.name, import_desc.asname

            enableFutureFeature(
                object_name = object_name,
                future_spec = source_ref.getFutureSpec(),
                source_ref  = source_ref
            )

        # Remember it for checks to be applied once module is complete.
        node.source_ref = source_ref
        _future_import_nodes.append( node )

    target_names = []
    import_names = []

    for import_desc in node.names:
        object_name, local_name = import_desc.name, import_desc.asname

        if object_name == "*":
            target_names.append( None )
        else:
            target_names.append( local_name if local_name is not None else object_name )

        import_names.append( object_name )

    if None in target_names:
        # More than "*" is a syntax error in Python, need not care about this at
        # all, it's only allowed value for import list in  this case.
        assert target_names == [ None ]

        # Python3 made this a syntax error unfortunately.
        if not provider.isPythonModule() and Utils.python_version >= 300:
            SyntaxErrors.raiseSyntaxError(
                "import * only allowed at module level",
                provider.getSourceReference()
            )

        if provider.isExpressionFunctionBody():
            provider.markAsStarImportContaining()

        return StatementImportStar(
            module_import = ExpressionImportModule(
                module_name = module_name,
                import_list = ( "*", ),
                level       = level,
                source_ref  = source_ref
            ),
            source_ref  = source_ref
        )
    else:
        import_nodes = []

        for target_name, import_name in zip( target_names, import_names ):
            import_nodes.append(
                StatementAssignmentVariable(
                    variable_ref = ExpressionTargetVariableRef(
                        variable_name = target_name,
                        source_ref    = source_ref
                    ),
                    source     = ExpressionImportName(
                        module      = ExpressionImportModule(
                            module_name = module_name,
                            import_list = import_names,
                            level       = level,
                            source_ref  = source_ref
                        ),
                        import_name = import_name,
                        source_ref  = source_ref
                    ),
                    source_ref = source_ref
                )
            )

        # Note: Each import is sequential. It can succeed, and the failure of a later one is
        # not changing one. We can therefore have a sequence of imports that only import one
        # thing therefore.
        return StatementsSequence(
            statements = import_nodes,
            source_ref = source_ref
        )
    def onEnterNode(self, node):
        # Mighty complex code with lots of branches and statements, but it
        # couldn't be less without making it more difficult.
        # pylint: disable=R0912,R0915

        if node.isExpressionTargetVariableRef():
            provider = node.getParentVariableProvider()

            if node.getVariable() is None:
                variable_name = node.getVariableName()

                variable = provider.getVariableForAssignment(
                    variable_name = variable_name
                )

                node.setVariable(variable)

            addVariableUsage(node.getVariable(), provider)
        elif node.isExpressionTargetTempVariableRef():
            provider = node.getParentVariableProvider()

            addVariableUsage(node.getVariable(), provider)
        elif node.isExpressionVariableRef():
            if node.getVariable() is None:
                provider = node.getParentVariableProvider()

                if provider.isEarlyClosure():
                    node.setVariable(
                        provider.getVariableForReference(
                            variable_name = node.getVariableName()
                        )
                    )
        elif node.isExpressionTempVariableRef():
            if node.getVariable().getOwner() != node.getParentVariableProvider():
                node.setVariable(
                    node.getParentVariableProvider().addClosureVariable(
                        node.getVariable()
                    )
                )

                assert node.getVariable().isClosureReference(), \
                  node.getVariable()
        elif node.isExpressionFunctionBody():
            if python_version >= 300:
                self._handleNonLocal(node)

            for variable in node.getParameters().getAllVariables():
                addVariableUsage(variable, node)

            # Python3.4 allows for class declarations to be made global, even
            # after they were declared, so we need to fix this up.
            if python_version >= 340 and node.isClassDictCreation():
                class_assign, qualname_assign = node.qualname_setup
                class_variable = class_assign.getTargetVariableRef().getVariable()

                if class_variable.isModuleVariable() and \
                   class_variable.isFromGlobalStatement():
                    qualname_node = qualname_assign.getAssignSource()

                    qualname_node.replaceWith(
                        makeConstantReplacementNode(
                            constant = class_variable.getName(),
                            node     = qualname_node
                        )
                    )

                    node.qualname_provider = node.getParentModule()

                    # TODO: Actually for nested global classes, this approach
                    # may not work, as their qualnames will be wrong. In that
                    # case a dedicated node for qualname references might be
                    # needed.

                del node.qualname_setup




        # Attribute access of names of class functions should be mangled, if
        # they start with "__", but do not end in "__" as well.
        elif node.isExpressionAttributeLookup() or \
             node.isStatementAssignmentAttribute() or \
             node.isStatementDelAttribute():
            attribute_name = node.getAttributeName()

            if attribute_name.startswith( "__" ) and \
               not attribute_name.endswith( "__" ):
                seen_function = False

                current = node

                while True:
                    current = current.getParentVariableProvider()

                    if current.isPythonModule():
                        break

                    assert current.isExpressionFunctionBody()

                    if current.isClassDictCreation():
                        if seen_function:
                            node.setAttributeName(
                                "_%s%s" % (
                                    current.getName().lstrip("_"),
                                    attribute_name
                                )
                            )

                        break
                    else:
                        seen_function = True
        # Check if continue and break are properly in loops. If not, raise a
        # syntax error.
        elif node.isStatementBreakLoop() or node.isStatementContinueLoop():
            current = node

            while True:
                if current.isPythonModule() or current.isExpressionFunctionBody():
                    if node.isStatementContinueLoop():
                        message = "'continue' not properly in loop"
                        col_offset   = 16 if python_version >= 300 else None
                        display_line = True
                        source_line  = None
                    else:
                        message = "'break' outside loop"

                        if isFullCompat():
                            col_offset   = 2 if python_version >= 300 else None
                            display_line = True
                            source_line  = "" if python_version >= 300 else None
                        else:
                            col_offset   = 13
                            display_line = True
                            source_line  = None

                    source_ref = node.getSourceReference()
                    # source_ref.line += 1

                    SyntaxErrors.raiseSyntaxError(
                        message,
                        source_ref   = node.getSourceReference(),
                        col_offset   = col_offset,
                        display_line = display_line,
                        source_line  = source_line
                    )

                current = current.getParent()

                if current.isStatementLoop():
                    break
def buildTryExceptionNode(provider, node, source_ref):
    # Try/except nodes. Re-formulated as described in the developer
    # manual. Exception handlers made the assignment to variables explicit. Same
    # for the "del" as done for Python3. Also catches always work a tuple of
    # exception types and hides away that they may be built or not.

    # Many variables, due to the re-formulation that is going on here, which
    # just has the complexity, pylint: disable=R0914

    tried = buildStatementsNode(
        provider   = provider,
        nodes      = node.body,
        source_ref = source_ref
    )

    handlers = []

    for handler in node.handlers:
        exception_expression, exception_assign, exception_block = (
            handler.type,
            handler.name,
            handler.body
        )

        if exception_assign is None:
            statements = [
                buildStatementsNode(
                    provider   = provider,
                    nodes      = exception_block,
                    source_ref = source_ref
                )
            ]
        elif Utils.python_version < 300:
            statements = [
                buildAssignmentStatements(
                    provider   = provider,
                    node       = exception_assign,
                    source     = ExpressionCaughtExceptionValueRef(
                        source_ref = source_ref.atInternal()
                    ),
                    source_ref = source_ref.atInternal()
                ),
                buildStatementsNode(
                    provider   = provider,
                    nodes      = exception_block,
                    source_ref = source_ref
                )
            ]
        else:
            target_info = decodeAssignTarget(
                provider   = provider,
                node       = exception_assign,
                source_ref = source_ref,
            )

            kind, detail = target_info

            assert kind == "Name", kind
            kind = "Name_Exception"

            statements = [
                buildAssignmentStatements(
                    provider   = provider,
                    node       = exception_assign,
                    source     = ExpressionCaughtExceptionValueRef(
                        source_ref = source_ref.atInternal()
                    ),
                    source_ref = source_ref.atInternal()
                ),
                makeTryFinallyStatement(
                    tried      = buildStatementsNode(
                        provider   = provider,
                        nodes      = exception_block,
                        source_ref = source_ref
                    ),
                    final      = buildDeleteStatementFromDecoded(
                        kind       = kind,
                        detail     = detail,
                        source_ref = source_ref
                    ),
                    source_ref = source_ref
                )
            ]

        handler_body = makeStatementsSequence(
            statements = statements,
            allow_none = True,
            source_ref = source_ref
        )

        exception_types = buildNode(
            provider   = provider,
            node       = exception_expression,
            source_ref = source_ref,
            allow_none = True
        )

        # The exception types should be a tuple, so as to be most general.
        if exception_types is None:
            if handler is not node.handlers[-1]:
                SyntaxErrors.raiseSyntaxError(
                    reason    = "default 'except:' must be last",
                    source_ref = source_ref.atLineNumber(
                        handler.lineno-1
                          if Options.isFullCompat() else
                        handler.lineno
                    )
                )

        handlers.append(
            (
                exception_types,
                handler_body,
            )
        )

    # Reraise by default
    exception_handling = makeReraiseExceptionStatement(
        source_ref  = source_ref
    )

    for exception_type, handler in reversed(handlers):
        if exception_type is None:
            # A default handler was given, so use that indead.
            exception_handling = handler
        else:
            exception_handling = StatementsSequence(
                statements = (
                    StatementConditional(
                        condition = ExpressionComparisonExceptionMatch(
                            left       = ExpressionCaughtExceptionTypeRef(
                                source_ref  = exception_type.source_ref
                            ),
                            right      = exception_type,
                            source_ref = exception_type.source_ref
                        ),
                        yes_branch = handler,
                        no_branch  = exception_handling,
                        source_ref = exception_type.source_ref
                    ),
                ),
                source_ref = exception_type.source_ref
            )

    prelude = (
        StatementPreserveFrameException(
            source_ref = source_ref.atInternal()
        ),
        StatementPublishException(
            source_ref = source_ref.atInternal()
        )
    )

    if exception_handling is None:
        # For Python3, we need not publish at all, if all we do is to revert
        # that immediately. For Python2, the publish may release previously
        # published exception, which has side effects potentially.
        if Utils.python_version < 300:
            exception_handling = StatementsSequence(
                statements = prelude,
                source_ref = source_ref.atInternal()
            )

            public_exc = True
        else:
            public_exc = False
    else:
        public_exc = True

        if Utils.python_version < 300:
            exception_handling.setStatements(
                prelude + exception_handling.getStatements()
            )
        else:
            exception_handling = StatementsSequence(
                statements = prelude + (
                    makeTryFinallyStatement(
                        tried = exception_handling,
                        final = StatementRestoreFrameException(
                            source_ref = source_ref.atInternal()
                        ),
                        source_ref = source_ref
                    ),
                ),
                source_ref = source_ref.atInternal()
            )

    no_raise = buildStatementsNode(
        provider   = provider,
        nodes      = node.orelse,
        source_ref = source_ref
    )

    if no_raise is None:
        return StatementTryExcept(
            tried      = tried,
            handling   = exception_handling,
            public_exc = public_exc,
            source_ref = source_ref
        )
    else:
        return makeTryExceptNoRaise(
            provider   = provider,
            temp_scope = provider.allocateTempScope("try_except"),
            handling   = exception_handling,
            tried      = tried,
            public_exc = public_exc,
            no_raise   = no_raise,
            source_ref = source_ref
        )
def buildTryExceptionNode(provider, node, source_ref):
    # Try/except nodes. Re-formulated as described in the developer
    # manual. Exception handlers made the assignment to variables explicit. Same
    # for the "del" as done for Python3. Also catches always work a tuple of
    # exception types and hides away that they may be built or not.

    # Many variables, due to the re-formulation that is going on here, which
    # just has the complexity, pylint: disable=R0914

    tried = buildStatementsNode(provider=provider,
                                nodes=node.body,
                                source_ref=source_ref)

    handlers = []

    for handler in node.handlers:
        exception_expression, exception_assign, exception_block = (
            handler.type, handler.name, handler.body)

        if exception_assign is None:
            statements = [
                buildStatementsNode(provider=provider,
                                    nodes=exception_block,
                                    source_ref=source_ref)
            ]
        elif Utils.python_version < 300:
            statements = [
                buildAssignmentStatements(
                    provider=provider,
                    node=exception_assign,
                    source=ExpressionCaughtExceptionValueRef(
                        source_ref=source_ref.atInternal()),
                    source_ref=source_ref.atInternal()),
                buildStatementsNode(provider=provider,
                                    nodes=exception_block,
                                    source_ref=source_ref)
            ]
        else:
            target_info = decodeAssignTarget(
                provider=provider,
                node=exception_assign,
                source_ref=source_ref,
            )

            kind, detail = target_info

            assert kind == "Name", kind
            kind = "Name_Exception"

            statements = [
                buildAssignmentStatements(
                    provider=provider,
                    node=exception_assign,
                    source=ExpressionCaughtExceptionValueRef(
                        source_ref=source_ref.atInternal()),
                    source_ref=source_ref.atInternal()),
                makeTryFinallyStatement(tried=buildStatementsNode(
                    provider=provider,
                    nodes=exception_block,
                    source_ref=source_ref),
                                        final=buildDeleteStatementFromDecoded(
                                            kind=kind,
                                            detail=detail,
                                            source_ref=source_ref),
                                        source_ref=source_ref)
            ]

        handler_body = makeStatementsSequence(statements=statements,
                                              allow_none=True,
                                              source_ref=source_ref)

        exception_types = buildNode(provider=provider,
                                    node=exception_expression,
                                    source_ref=source_ref,
                                    allow_none=True)

        # The exception types should be a tuple, so as to be most general.
        if exception_types is None:
            if handler is not node.handlers[-1]:
                SyntaxErrors.raiseSyntaxError(
                    reason="default 'except:' must be last",
                    source_ref=source_ref.atLineNumber(
                        handler.lineno -
                        1 if Options.isFullCompat() else handler.lineno))

        handlers.append((
            exception_types,
            handler_body,
        ))

    # Reraise by default
    exception_handling = makeReraiseExceptionStatement(source_ref=source_ref)

    for exception_type, handler in reversed(handlers):
        if exception_type is None:
            # A default handler was given, so use that indead.
            exception_handling = handler
        else:
            exception_handling = StatementsSequence(
                statements=(StatementConditional(
                    condition=ExpressionComparisonExceptionMatch(
                        left=ExpressionCaughtExceptionTypeRef(
                            source_ref=exception_type.source_ref),
                        right=exception_type,
                        source_ref=exception_type.source_ref),
                    yes_branch=handler,
                    no_branch=exception_handling,
                    source_ref=exception_type.source_ref), ),
                source_ref=exception_type.source_ref)

    prelude = (StatementPreserveFrameException(
        source_ref=source_ref.atInternal()),
               StatementPublishException(source_ref=source_ref.atInternal()))

    if exception_handling is None:
        # For Python3, we need not publish at all, if all we do is to revert
        # that immediately. For Python2, the publish may release previously
        # published exception, which has side effects potentially.
        if Utils.python_version < 300:
            exception_handling = StatementsSequence(
                statements=prelude, source_ref=source_ref.atInternal())

            public_exc = True
        else:
            public_exc = False
    else:
        public_exc = True

        if Utils.python_version < 300:
            exception_handling.setStatements(
                prelude + exception_handling.getStatements())
        else:
            exception_handling = StatementsSequence(
                statements=prelude + (makeTryFinallyStatement(
                    tried=exception_handling,
                    final=StatementRestoreFrameException(
                        source_ref=source_ref.atInternal()),
                    source_ref=source_ref), ),
                source_ref=source_ref.atInternal())

    no_raise = buildStatementsNode(provider=provider,
                                   nodes=node.orelse,
                                   source_ref=source_ref)

    if no_raise is None:
        return StatementTryExcept(tried=tried,
                                  handling=exception_handling,
                                  public_exc=public_exc,
                                  source_ref=source_ref)
    else:
        return makeTryExceptNoRaise(
            provider=provider,
            temp_scope=provider.allocateTempScope("try_except"),
            handling=exception_handling,
            tried=tried,
            public_exc=public_exc,
            no_raise=no_raise,
            source_ref=source_ref)
Exemple #54
0
def buildImportFromNode(provider, node, source_ref):
    # "from .. import .." statements. This may trigger a star import, or multiple names
    # being looked up from the given module variable name.

    module_name = node.module if node.module is not None else ""
    level = node.level

    # Importing from "__future__" module may enable flags.
    if module_name == "__future__":
        assert provider.isPythonModule() or source_ref.isExecReference()

        for import_desc in node.names:
            object_name, _local_name = import_desc.name, import_desc.asname

            enableFutureFeature(object_name=object_name,
                                future_spec=source_ref.getFutureSpec(),
                                source_ref=source_ref)

        # Remember it for checks to be applied once module is complete.
        node.source_ref = source_ref
        _future_import_nodes.append(node)

    target_names = []
    import_names = []

    for import_desc in node.names:
        object_name, local_name = import_desc.name, import_desc.asname

        if object_name == "*":
            target_names.append(None)
        else:
            target_names.append(
                local_name if local_name is not None else object_name)

        import_names.append(object_name)

    if None in target_names:
        # More than "*" is a syntax error in Python, need not care about this at
        # all, it's only allowed value for import list in  this case.
        assert target_names == [None]

        # Python3 made this a syntax error unfortunately.
        if not provider.isPythonModule() and Utils.python_version >= 300:
            SyntaxErrors.raiseSyntaxError(
                "import * only allowed at module level",
                provider.getSourceReference())

        if provider.isExpressionFunctionBody():
            provider.markAsStarImportContaining()

        return StatementImportStar(module_import=ExpressionImportModule(
            module_name=module_name,
            import_list=("*", ),
            level=level,
            source_ref=source_ref),
                                   source_ref=source_ref)
    else:
        import_nodes = []

        for target_name, import_name in zip(target_names, import_names):
            import_nodes.append(
                StatementAssignmentVariable(
                    variable_ref=ExpressionTargetVariableRef(
                        variable_name=target_name, source_ref=source_ref),
                    source=ExpressionImportName(module=ExpressionImportModule(
                        module_name=module_name,
                        import_list=import_names,
                        level=level,
                        source_ref=source_ref),
                                                import_name=import_name,
                                                source_ref=source_ref),
                    source_ref=source_ref))

        # Note: Each import is sequential. It can succeed, and the failure of a later one is
        # not changing one. We can therefore have a sequence of imports that only import one
        # thing therefore.
        return StatementsSequence(statements=import_nodes,
                                  source_ref=source_ref)
Exemple #55
0
    def onEnterNode(self, node):
        # Mighty complex code with lots of branches and statements, but it
        # couldn't be less without making it more difficult.
        # pylint: disable=R0912,R0915

        if node.isExpressionTargetVariableRef():
            provider = node.getParentVariableProvider()

            if node.getVariable() is None:
                variable_name = node.getVariableName()

                variable = provider.getVariableForAssignment(
                    variable_name = variable_name
                )

                node.setVariable(variable)

            addVariableUsage(node.getVariable(), provider)
        elif node.isExpressionTargetTempVariableRef():
            provider = node.getParentVariableProvider()

            addVariableUsage(node.getVariable(), provider)
        elif node.isExpressionVariableRef():
            if node.getVariable() is None:
                provider = node.getParentVariableProvider()

                if provider.isEarlyClosure():
                    variable = provider.getVariableForReference(
                        variable_name = node.getVariableName()
                    )

                    # Python3.4 version respects closure variables taken can be
                    # overridden by writes to locals. It should be done for
                    # globals too, on all versions, but for Python2 the locals
                    # dictionary is avoided unless "exec" appears, so it's not
                    # done.
                    if variable.getOwner() is not provider:
                        if python_version >= 340 or \
                           (python_version >= 300 and \
                            variable.isModuleVariable()):
                            variable = Variables.MaybeLocalVariable(
                                owner          = provider,
                                maybe_variable = variable
                            )

                    node.setVariable(variable)
        elif node.isExpressionTempVariableRef():
            if node.getVariable().getOwner() != node.getParentVariableProvider():
                node.setVariable(
                    node.getParentVariableProvider().addClosureVariable(
                        node.getVariable()
                    )
                )
        elif node.isExpressionFunctionBody():
            if python_version >= 300:
                self._handleNonLocal(node)

            for variable in node.getParameters().getAllVariables():
                addVariableUsage(variable, node)

            # Python3.4 allows for class declarations to be made global, even
            # after they were declared, so we need to fix this up.
            if python_version >= 340:
                self._handleQualnameSetup(node)
        # Attribute access of names of class functions should be mangled, if
        # they start with "__", but do not end in "__" as well.
        elif node.isExpressionAttributeLookup() or \
             node.isStatementAssignmentAttribute() or \
             node.isStatementDelAttribute():
            attribute_name = node.getAttributeName()

            if attribute_name.startswith("__") and \
               not attribute_name.endswith("__"):
                seen_function = False

                current = node

                while True:
                    current = current.getParentVariableProvider()

                    if current.isPythonModule():
                        break

                    assert current.isExpressionFunctionBody()

                    if current.isClassDictCreation():
                        if seen_function:
                            node.setAttributeName(
                                "_%s%s" % (
                                    current.getName().lstrip("_"),
                                    attribute_name
                                )
                            )

                        break
                    else:
                        seen_function = True
        # Check if continue and break are properly in loops. If not, raise a
        # syntax error.
        elif node.isStatementBreakLoop() or node.isStatementContinueLoop():
            current = node

            while True:
                if current.isPythonModule() or \
                   current.isExpressionFunctionBody():
                    if node.isStatementContinueLoop():
                        message = "'continue' not properly in loop"
                        col_offset   = 16 if python_version >= 300 else None
                        display_line = True
                        source_line  = None
                    else:
                        message = "'break' outside loop"

                        if isFullCompat():
                            col_offset   = 2 if python_version >= 300 else None
                            display_line = True
                            source_line  = "" if python_version >= 300 else None
                        else:
                            col_offset   = 13
                            display_line = True
                            source_line  = None

                    SyntaxErrors.raiseSyntaxError(
                        message,
                        source_ref   = node.getSourceReference(),
                        col_offset   = col_offset,
                        display_line = display_line,
                        source_line  = source_line
                    )

                current = current.getParent()

                if current.isStatementLoop():
                    break