예제 #1
0
 def _remover(node: LN, capture: Capture, filename: Filename) -> None:
     if node.type == 300:
         for ch in node.post_order():
             if isinstance(ch, Leaf) and ch.value == class_name:
                 if ch.next_sibling and ch.next_sibling.value == ",":
                     ch.next_sibling.remove()
                 ch.remove()
     elif node.type == 311:
         node.parent.remove()
     else:
         node.remove()
예제 #2
0
def modify_attr(node: LN, capture: Capture,
                filename: Filename) -> Optional[LN]:
    node.replace(
        Call(
            Name("getattr"),
            args=[
                capture["obj"].clone(),
                Comma(),
                Space(),
                String('"' + capture["attr"].value + '"'),
            ],
        ))
예제 #3
0
 def remove_super_init_call_modifier(node: LN, capture: Capture,
                                     filename: Filename) -> None:
     for ch in node.post_order():
         if isinstance(ch, Leaf) and ch.value == "super":
             if any(c.value for c in ch.parent.post_order()
                    if isinstance(c, Leaf)):
                 ch.parent.remove()
예제 #4
0
 def _remover(node: LN, capture: Capture, filename: Filename) -> None:
     node.remove()
예제 #5
0
def m_add_type_comment(node: LN, capture: Capture, filename: Filename,
                       threadlocals) -> LN:
    """
    (modifier)

    Adds type comment annotations for functions, as understood by
    `mypy --py2` type checking.
    """
    threadlocals.docstring_count += 1
    # since we filtered for funcs with a docstring, the initial_indent_node
    # should be the indent before the start of the docstring quotes.
    initial_indent = capture["initial_indent_node"]
    function: Leaf = capture["function_name"]

    try:
        doc_annotation = docstring_parser.parse(
            capture["docstring_node"].value)
    except parsy.ParseError as e:
        report_parse_error(e, function)
        raise Interrupt

    if not doc_annotation.has_types:
        raise Interrupt

    annotation_arg_names = (doc_annotation.arg_types.args.keys()
                            if doc_annotation.arg_types else set())
    signature_name, signature_arg_names = threadlocals.signatures[
        node.get_lineno()]
    assert signature_name == function.value, f"{signature_name} != {function.value}"

    if doc_annotation.arg_types and not annotation_arg_names == set(
            signature_arg_names):
        report_doc_args_signature_mismatch_error(function)
        raise Interrupt
    # we either have no annotation args, or we do and the names match the signature

    # are we okay to annotate?
    # TODO these are currently WARN/FAIL... maybe should be OK/WARN/FAIL
    # configurably, like for amibiguous types
    if signature_arg_names and (not doc_annotation.arg_types or
                                not doc_annotation.arg_types.is_fully_typed):
        report_incomplete_arg_types(function)
        if not threadlocals.settings.ALLOW_UNTYPED_ARGS:
            raise Interrupt
    elif not signature_arg_names and not doc_annotation.arg_types:
        # special case: replace doc_annotation with one having empty args
        # (rather than `None`)
        doc_annotation = TypeSignature.factory(
            arg_types=ArgTypes.no_args_factory(),
            return_type=doc_annotation.return_type,
        )

    if not doc_annotation.return_type or not doc_annotation.return_type.is_fully_typed:
        report_incomplete_return_type(function)
        if threadlocals.settings.REQUIRE_RETURN_TYPE:
            raise Interrupt

    # yes, annotate...
    threadlocals.typed_docstring_count += 1

    # print(doc_annotation.return_type, doc_annotation.return_type.is_fully_typed, doc_annotation.return_type.name is ReturnsSection.YIELDS)
    if (doc_annotation.return_type
            and doc_annotation.return_type.is_fully_typed
            and doc_annotation.return_type.name is ReturnsSection.YIELDS):
        report_generator_annotation(function)

    # record the types we found in this docstring
    # and warn/fail on ambiguous types according to IMPORT_COLLISION_POLICY
    name_to_strategy: Dict[str, ImportStrategy] = {}
    for name in doc_annotation.type_names():
        try:
            name_to_strategy[
                name] = threadlocals.import_strategist.get_for_name(name)
        except AmbiguousTypeError as e:
            report_ambiguous_type_error(e, function)
            if e.should_fail:
                raise Interrupt

    record_type_names(name_to_strategy)

    # add the type comment as first line of func body (before docstring)
    type_comment = get_type_comment(doc_annotation, name_to_strategy)
    initial_indent.prefix = f"{initial_indent}{type_comment}\n"
    threadlocals.comment_count += 1

    # remove types from docstring
    new_docstring_node = capture["docstring_node"].clone()
    new_docstring_node.value = remove_types(
        docstring=capture["docstring_node"].value,
        signature=doc_annotation,
    )
    capture["docstring_node"].replace(new_docstring_node)

    return node
 def _remover(node: LN, capture: Capture, filename: Filename) -> None:
     if node.type not in (300, 311):  # remove only definition
         node.remove()
예제 #7
0
def corrector(node: LN, capture: Capture, filename: Filename) -> Optional[LN]:
    node.value = fix_spelling(node.value)
    return node