Esempio n. 1
0
 def visit_JoinedStr(self, n: ast3.JoinedStr) -> Expression:
     result_expression = StrExpr('')  # type: Expression
     for value_expr in self.translate_expr_list(n.values):
         string_method = MemberExpr(value_expr, '__str__')
         string_method.set_line(value_expr)
         stringified_value_expr = CallExpr(string_method, [], [])
         stringified_value_expr.set_line(value_expr)
         result_expression = OpExpr('+', result_expression,
                                    stringified_value_expr)
         result_expression.set_line(value_expr)
     return result_expression
Esempio n. 2
0
 def visit_JoinedStr(self, n: ast3.JoinedStr) -> Expression:
     arg_count = len(n.values)
     format_string = StrExpr('{}' * arg_count)
     format_string.set_line(n.lineno, n.col_offset)
     format_method = MemberExpr(format_string, 'format')
     format_method.set_line(format_string)
     format_args = self.translate_expr_list(n.values)
     format_arg_kinds = [ARG_POS] * arg_count
     result_expression = CallExpr(format_method, format_args,
                                  format_arg_kinds)
     return result_expression
Esempio n. 3
0
 def visit_JoinedStr(self, n: ast3.JoinedStr) -> Expression:
     # Each of n.values is a str or FormattedValue; we just concatenate
     # them all using ''.join.
     empty_string = StrExpr('')
     empty_string.set_line(n.lineno, n.col_offset)
     strs_to_join = ListExpr(self.translate_expr_list(n.values))
     strs_to_join.set_line(empty_string)
     join_method = MemberExpr(empty_string, 'join')
     join_method.set_line(empty_string)
     result_expression = CallExpr(join_method, [strs_to_join],
                                  [ARG_POS], [None])
     return result_expression
Esempio n. 4
0
 def visit_FormattedValue(self, n: ast3.FormattedValue) -> Expression:
     # A FormattedValue is a component of a JoinedStr, or it can exist
     # on its own. We translate them to individual '{}'.format(value)
     # calls -- we don't bother with the conversion/format_spec fields.
     exp = self.visit(n.value)
     exp.set_line(n.lineno, n.col_offset)
     format_string = StrExpr('{}')
     format_string.set_line(n.lineno, n.col_offset)
     format_method = MemberExpr(format_string, 'format')
     format_method.set_line(format_string)
     result_expression = CallExpr(format_method, [exp], [ARG_POS])
     return result_expression
Esempio n. 5
0
 def visit_JoinedStr(self, n: ast3.JoinedStr) -> Expression:
     # Each of n.values is a str or FormattedValue; we just concatenate
     # them all using ''.join.
     empty_string = StrExpr('')
     empty_string.set_line(n.lineno, n.col_offset)
     strs_to_join = ListExpr(self.translate_expr_list(n.values))
     strs_to_join.set_line(empty_string)
     join_method = MemberExpr(empty_string, 'join')
     join_method.set_line(empty_string)
     result_expression = CallExpr(join_method,
                                  [strs_to_join],
                                  [ARG_POS],
                                  [None])
     return result_expression
Esempio n. 6
0
 def visit_FormattedValue(self, n: ast3.FormattedValue) -> Expression:
     # A FormattedValue is a component of a JoinedStr, or it can exist
     # on its own. We translate them to individual '{}'.format(value)
     # calls -- we don't bother with the conversion/format_spec fields.
     exp = self.visit(n.value)
     exp.set_line(n.lineno, n.col_offset)
     format_string = StrExpr('{}')
     format_string.set_line(n.lineno, n.col_offset)
     format_method = MemberExpr(format_string, 'format')
     format_method.set_line(format_string)
     result_expression = CallExpr(format_method,
                                  [exp],
                                  [ARG_POS],
                                  [None])
     return result_expression
def add_kw_props(cls: ClassDef, kw_class: ClassDef,
                 api: SemanticAnalyzerPluginInterface) -> None:
    try:
        ans_cls_expr = kw_class.keywords['ans_type']
        kw_set_expr = kw_class.keywords['extra_kws']
    except KeyError:
        api.fail(
            'Both `ans_type` and `extra_kws` are required to subclass '
            'KeywordsMixin',
            kw_class,
            code=CALL_ARG)
        return

    if not isinstance(ans_cls_expr, RefExpr):
        print('Wrong instance type for ans_type argument')
        return

    ans_cls_node = ans_cls_expr.node

    if not isinstance(ans_cls_node, TypeInfo):
        print('Got incorrect type for Ansible type node')
        return

    if not (isinstance(kw_set_expr, SetExpr)
            or is_empty_set_expr(kw_set_expr)):
        print('Wrong instance type for extra_kws')
        return

    # Can be an empty set, where we don't need to add any more properties.
    if isinstance(kw_set_expr, SetExpr):
        for kw_expr in kw_set_expr.items:
            add_property(cls.info, ans_cls_node, kw_expr, api)

    # Also add one for name
    add_property(cls.info, ans_cls_node, StrExpr('name'), api)
Esempio n. 8
0
 def visit_Str(self, n: ast3.Str) -> Union[UnicodeExpr, StrExpr]:
     # Hack: assume all string literals in Python 2 stubs are normal
     # strs (i.e. not unicode).  All stubs are parsed with the Python 3
     # parser, which causes unprefixed string literals to be interpreted
     # as unicode instead of bytes.  This hack is generally okay,
     # because mypy considers str literals to be compatible with
     # unicode.
     return StrExpr(n.s)
Esempio n. 9
0
    def visit_Bytes(self, n: ast35.Bytes) -> Node:
        # The following line is a bit hacky, but is the best way to maintain
        # compatibility with how mypy currently parses the contents of bytes literals.
        contents = str(n.s)[2:-1]

        if self.pyversion[0] >= 3:
            return BytesExpr(contents)
        else:
            return StrExpr(contents)
Esempio n. 10
0
    def check_specs_in_format_call(self, call: CallExpr,
                                   specs: List[ConversionSpecifier], format_value: str) -> None:
        """Perform pairwise checks for conversion specifiers vs their replacements.

        The core logic for format checking is implemented in this method.
        """
        assert all(s.key for s in specs), "Keys must be auto-generated first!"
        replacements = self.find_replacements_in_call(call, [cast(str, s.key) for s in specs])
        assert len(replacements) == len(specs)
        for spec, repl in zip(specs, replacements):
            repl = self.apply_field_accessors(spec, repl, ctx=call)
            actual_type = repl.type if isinstance(repl, TempNode) else self.chk.type_map.get(repl)
            assert actual_type is not None

            # Special case custom formatting.
            if (spec.format_spec and spec.non_standard_format_spec and
                    # Exclude "dynamic" specifiers (i.e. containing nested formatting).
                    not ('{' in spec.format_spec or '}' in spec.format_spec)):
                if (not custom_special_method(actual_type, '__format__', check_all=True) or
                        spec.conversion):
                    # TODO: add support for some custom specs like datetime?
                    self.msg.fail('Unrecognized format'
                                  ' specification "{}"'.format(spec.format_spec[1:]),
                                  call, code=codes.STRING_FORMATTING)
                    continue
            # Adjust expected and actual types.
            if not spec.type:
                expected_type = AnyType(TypeOfAny.special_form)  # type: Optional[Type]
            else:
                assert isinstance(call.callee, MemberExpr)
                if isinstance(call.callee.expr, (StrExpr, UnicodeExpr)):
                    format_str = call.callee.expr
                else:
                    format_str = StrExpr(format_value)
                expected_type = self.conversion_type(spec.type, call, format_str,
                                                     format_call=True)
            if spec.conversion is not None:
                # If the explicit conversion is given, then explicit conversion is called _first_.
                if spec.conversion[1] not in 'rsa':
                    self.msg.fail('Invalid conversion type "{}",'
                                  ' must be one of "r", "s" or "a"'.format(spec.conversion[1]),
                                  call, code=codes.STRING_FORMATTING)
                actual_type = self.named_type('builtins.str')

            # Perform the checks for given types.
            if expected_type is None:
                continue

            a_type = get_proper_type(actual_type)
            actual_items = (get_proper_types(a_type.items) if isinstance(a_type, UnionType)
                            else [a_type])
            for a_type in actual_items:
                if custom_special_method(a_type, '__format__'):
                    continue
                self.check_placeholder_type(a_type, expected_type, call)
                self.perform_special_format_checks(spec, call, repl, a_type, expected_type)
Esempio n. 11
0
    def visit_Str(self, s: ast27.Str) -> Expression:
        # Hack: assume all string literals in Python 2 stubs are normal
        # strs (i.e. not unicode).  All stubs are parsed with the Python 3
        # parser, which causes unprefixed string literals to be interpreted
        # as unicode instead of bytes.  This hack is generally okay,
        # because mypy considers str literals to be compatible with
        # unicode.
        if isinstance(s.s, bytes):
            n = s.s
            # The following line is a bit hacky, but is the best way to maintain
            # compatibility with how mypy currently parses the contents of bytes literals.
            contents = str(n)[2:-1]

            if self.pyversion[0] >= 3:
                return BytesExpr(contents)
            else:
                return StrExpr(contents)
        else:
            if self.pyversion[0] >= 3 or self.is_stub:
                return StrExpr(s.s)
            else:
                return UnicodeExpr(s.s)
Esempio n. 12
0
    def validate_and_transform_accessors(self, temp_ast: Expression,
                                         original_repl: Expression,
                                         spec: ConversionSpecifier,
                                         ctx: Context) -> bool:
        """Validate and transform (in-place) format field accessors.

        On error, report it and return False. The transformations include replacing the dummy
        variable with actual replacement expression and translating any name expressions in an
        index into strings, so that this will work:

            class User(TypedDict):
                name: str
                id: int
            u: User
            '{[id]:d} -> {[name]}'.format(u)
        """
        if not isinstance(temp_ast, (MemberExpr, IndexExpr)):
            self.msg.fail('Only index and member expressions are allowed in'
                          ' format field accessors; got "{}"'.format(
                              spec.field),
                          ctx,
                          code=codes.STRING_FORMATTING)
            return False
        if isinstance(temp_ast, MemberExpr):
            node = temp_ast.expr
        else:
            node = temp_ast.base
            if not isinstance(temp_ast.index, (NameExpr, IntExpr)):
                assert spec.key, "Call this method only after auto-generating keys!"
                assert spec.field
                self.msg.fail('Invalid index expression in format field'
                              ' accessor "{}"'.format(
                                  spec.field[len(spec.key):]),
                              ctx,
                              code=codes.STRING_FORMATTING)
                return False
            if isinstance(temp_ast.index, NameExpr):
                temp_ast.index = StrExpr(temp_ast.index.name)
        if isinstance(node, NameExpr) and node.name == DUMMY_FIELD_NAME:
            # Replace it with the actual replacement expression.
            assert isinstance(
                temp_ast, (IndexExpr, MemberExpr))  # XXX: this is redundant
            if isinstance(temp_ast, IndexExpr):
                temp_ast.base = original_repl
            else:
                temp_ast.expr = original_repl
            return True
        node.line = ctx.line
        node.column = ctx.column
        return self.validate_and_transform_accessors(
            node, original_repl=original_repl, spec=spec, ctx=ctx)
Esempio n. 13
0
 def visit_Str(self, n: ast27.Str) -> Expression:
     # Note: typed_ast.ast27 will handled unicode_literals for us. If
     # n.s is of type 'bytes', we know unicode_literals was not enabled;
     # otherwise we know it was.
     #
     # Note that the following code is NOT run when parsing Python 2.7 stubs:
     # we always parse stub files (no matter what version) using the Python 3
     # parser. This is also why string literals in Python 2.7 stubs are assumed
     # to be unicode.
     if isinstance(n.s, bytes):
         contents = bytes_to_human_readable_repr(n.s)
         e = StrExpr(contents, from_python_3=False)  # type: Union[StrExpr, UnicodeExpr]
         return self.set_line(e, n)
     else:
         e = UnicodeExpr(n.s)
         return self.set_line(e, n)
Esempio n. 14
0
 def visit_Str(self, n: ast27.Str) -> Expression:
     # Hack: assume all string literals in Python 2 stubs are normal
     # strs (i.e. not unicode).  All stubs are parsed with the Python 3
     # parser, which causes unprefixed string literals to be interpreted
     # as unicode instead of bytes.  This hack is generally okay,
     # because mypy considers str literals to be compatible with
     # unicode.
     if isinstance(n.s, bytes):
         value = n.s
         # The following line is a bit hacky, but is the best way to maintain
         # compatibility with how mypy currently parses the contents of bytes literals.
         contents = str(value)[2:-1]
         e = StrExpr(contents)  # type: Union[StrExpr, UnicodeExpr]
         return self.set_line(e, n)
     else:
         e = UnicodeExpr(n.s)
         return self.set_line(e, n)
Esempio n. 15
0
 def visit_Str(self, n: ast35.Str) -> Node:
     return StrExpr(n.s)
Esempio n. 16
0
 def visit_str_expr(self, node: StrExpr) -> Node:
     return StrExpr(node.value)
Esempio n. 17
0
 def visit_Str(self, n):
     return StrExpr(n.s)
Esempio n. 18
0
 def visit_str_expr(self, node: StrExpr) -> StrExpr:
     return StrExpr(node.value, node.from_python_3)