Example #1
0
    def test_to_named_class_def(self) -> None:
        """ Test that find_ast_type gives the wrapped named class back """

        class_def = ClassDef(
            name="foo",
            bases=tuple(),
            keywords=tuple(),
            decorator_list=[],
            body=[],
            expr=None,
            identifier_name=None,
        )
        run_ast_test(
            self,
            find_ast_type(
                Module(
                    body=[
                        ClassDef(
                            name="bar",
                            bases=tuple(),
                            keywords=tuple(),
                            decorator_list=[],
                            body=[],
                            expr=None,
                            identifier_name=None,
                        ),
                        class_def,
                    ],
                    stmt=None,
                ),
                node_name="foo",
            ),
            class_def,
            skip_black=True,
        )
Example #2
0
    def test_find_ast_type_fails(self) -> None:
        """ Test that `find_ast_type` throws the right errors """

        self.assertRaises(NotImplementedError, lambda: find_ast_type(None))
        self.assertRaises(NotImplementedError, lambda: find_ast_type(""))
        self.assertRaises(TypeError,
                          lambda: find_ast_type(Module(body=[], stmt=None)))
        self.assertRaises(
            NotImplementedError,
            lambda: find_ast_type(
                Module(
                    body=[
                        ClassDef(expr=None, identifier_name=None),
                        ClassDef(expr=None, identifier_name=None),
                    ],
                    stmt=None,
                )),
        )
Example #3
0
    def test_find_ast_type(self) -> None:
        """ Test that `find_ast_type` gives the wrapped class back """

        class_def = ClassDef(
            name="",
            bases=tuple(),
            keywords=tuple(),
            decorator_list=[],
            body=[],
            expr=None,
            identifier_name=None,
        )
        run_ast_test(
            self,
            find_ast_type(Module(body=[class_def], stmt=None)),
            class_def,
            skip_black=True,
        )
Example #4
0
def class_(
    class_def,
    class_name=None,
    merge_inner_function=None,
    infer_type=False,
    word_wrap=True,
):
    """
    Converts an AST to our IR

    :param class_def: Class AST or Module AST with a ClassDef inside
    :type class_def: ```Union[Module, ClassDef]```

    :param class_name: Name of `class`. If None, gives first found.
    :type class_name: ```Optional[str]```

    :param merge_inner_function: Name of inner function to merge. If None, merge nothing.
    :type merge_inner_function: ```Optional[str]```

    :param infer_type: Whether to try inferring the typ (from the default)
    :type infer_type: ```bool```

    :param word_wrap: Whether to word-wrap. Set `DOCTRANS_LINE_LENGTH` to configure length.
    :type word_wrap: ```bool```

    :returns: a dictionary of form
        {  "name": Optional[str],
           "type": Optional[str],
           "doc": Optional[str],
           "params": OrderedDict[str, {'typ': str, 'doc': Optional[str], 'default': Any}]
           "returns": Optional[OrderedDict[Literal['return_type'],
                                           {'typ': str, 'doc': Optional[str], 'default': Any}),)]] }
    :rtype: ```dict```
    """
    assert not isinstance(class_def, FunctionDef)
    is_supported_ast_node = isinstance(class_def, (Module, ClassDef))
    if not is_supported_ast_node and isinstance(class_def, type):
        ir = _inspect(class_def, class_name, word_wrap)
        parsed_body = ast.parse(getsource(class_def).lstrip()).body[0]
        parsed_body.body = (parsed_body.body
                            if ast.get_docstring(parsed_body) is None else
                            parsed_body.body[1:])

        if merge_inner_function is not None:
            _merge_inner_function(
                parsed_body,
                infer_type=infer_type,
                intermediate_repr=ir,
                merge_inner_function=merge_inner_function,
            )
            return ir

        ir["_internal"] = {
            "body":
            list(
                filterfalse(
                    rpartial(isinstance, AnnAssign),
                    parsed_body.body,
                )),
            "from_name":
            class_name,
            "from_type":
            "cls",
        }
        body_ir = class_(
            class_def=parsed_body,
            class_name=class_name,
            merge_inner_function=merge_inner_function,
        )
        ir_merge(ir, body_ir)

        return ir

    assert (is_supported_ast_node
            ), "Expected 'Union[Module, ClassDef]' got `{!r}`".format(
                type(class_def).__name__)
    class_def = find_ast_type(class_def, class_name)
    doc_str = get_docstring(class_def)
    intermediate_repr = ({
        "name": class_name,
        "type": "static",
        "doc": "",
        "params": OrderedDict(),
        "returns": None,
    } if doc_str is None else docstring(get_docstring(class_def).replace(
        ":cvar", ":param"),
                                        emit_default_doc=False))

    if "return_type" in intermediate_repr["params"]:
        intermediate_repr["returns"] = OrderedDict(
            (("return_type",
              intermediate_repr["params"].pop("return_type")), ))

    body = class_def.body if doc_str is None else class_def.body[1:]
    for e in body:
        if isinstance(e, AnnAssign):
            typ = to_code(e.annotation).rstrip("\n")
            val = (lambda v: {
                "default": NoneStr
            } if v is None else {
                "default":
                v if type(v).__name__ in simple_types else (lambda value: {
                    "{}": {} if isinstance(v, Dict) else set(),
                    "[]": [],
                    "()": (),
                }.get(value, parse_to_scalar(value)))(to_code(v).rstrip("\n"))
            })(get_value(get_value(e)))
            # if 'str' in typ and val: val["default"] = val["default"].strip("'")  # Unquote?
            typ_default = dict(typ=typ, **val)

            for key in "params", "returns":
                if e.target.id in (intermediate_repr[key] or iter(())):
                    intermediate_repr[key][e.target.id].update(typ_default)
                    typ_default = False
                    break

            if typ_default:
                k = "returns" if e.target.id == "return_type" else "params"
                if intermediate_repr.get(k) is None:
                    intermediate_repr[k] = OrderedDict()
                intermediate_repr[k][e.target.id] = typ_default
        elif isinstance(e, Assign):
            val = get_value(e)
            if val is not None:
                val = get_value(val)
                deque(
                    map(
                        lambda target: setitem(*(
                            (intermediate_repr["params"][target.id], "default",
                             val)
                            if target.id in intermediate_repr["params"] else (
                                intermediate_repr["params"],
                                target.id,
                                {
                                    "default": val
                                },
                            ))),
                        e.targets,
                    ),
                    maxlen=0,
                )

    intermediate_repr.update({
        "params":
        OrderedDict(
            map(
                partial(_set_name_and_type,
                        infer_type=infer_type,
                        word_wrap=word_wrap),
                intermediate_repr["params"].items(),
            )),
        "_internal": {
            "body":
            list(filterfalse(rpartial(isinstance, (AnnAssign, Assign)), body)),
            "from_name":
            class_def.name,
            "from_type":
            "cls",
        },
    })

    if merge_inner_function is not None:
        assert isinstance(class_def, ClassDef)

        _merge_inner_function(
            class_def,
            infer_type=infer_type,
            intermediate_repr=intermediate_repr,
            merge_inner_function=merge_inner_function,
        )

    # intermediate_repr['_internal']["body"]= list(filterfalse(rpartial(isinstance,(AnnAssign,Assign)),class_def.body))

    return intermediate_repr