def build_return_type_info(sig) -> str:
    return_type = "None"
    if sig.return_annotation != inspect.Signature.empty:
        return_type = portable_type_name(sig.return_annotation)
        if return_type == "object":
            return_type = repr(sig.return_annotation).replace(
                "<class '", "").replace("'>", "").replace("typing.", "")
    return return_type
def build_signature_info(sig) -> List[Any]:
    args = []
    for p in sig.parameters.values():
        if p.name in ("secrets", "configuration"):
            continue

        arg = {"name": p.name, "required": "Yes"}

        if p.annotation != inspect.Parameter.empty:
            arg["type"] = portable_type_name(p.annotation)

        if p.default != inspect.Parameter.empty:
            arg["required"] = "No"
            if isinstance(p.default, str):
                arg["default"] = '"{}"'.format(p.default)
            else:
                arg["default"] = json.dumps(p.default)
        args.append(arg)

    return args
Beispiel #3
0
def import_extension(extension: Dict[str, str]) -> Dict[str, Any]:
    pkg = importlib.import_module(extension["name"])

    try:
        readme = pkgutil.get_data(
            extension["name"], "../README.md").decode('utf-8')
        _, readme = readme.split("\n", 1)
    except FileNotFoundError as x:
        print("Failed to find README in {}: {}".format(
            extension["name"], str(x)))
        readme = "N/A"

    meta = {
        "ext": {
            "name": extension["name"],
            "version": pkg.__version__,
            "repo_url": extension["repo"]
        },
        "readme": readme,
        "activities": {}
    }

    walker = pkgutil.walk_packages(
        pkg.__path__, pkg.__name__ + ".")
    for (module_loader, mod_name, ispkg) in walker:
        if mod_name.endswith(".types"):
            continue

        if ispkg:
            continue

        mod = importlib.import_module(mod_name)
        exported = getattr(mod, "__all__", [])
        if not exported:
            continue

        activities = []
        target = mod_name.rsplit(".", 2)[1]
        if target not in meta["activities"]:
            meta["activities"][target] = activities
        else:
            activities = meta["activities"][target]

        for func_name in exported:
            func = getattr(mod, func_name)
            sig = inspect.signature(func)

            activity_type = ""
            mod_lastname = mod_name.rsplit(".", 1)[1]
            if mod_lastname == "actions":
                activity_type = "action"
            elif mod_lastname == "probes":
                activity_type = "probe"

            meta["activities"]
            args = []
            for p in sig.parameters.values():
                if p.name in ("secrets", "configuration"):
                    continue

                arg = {
                    "name": p.name,
                    "required": "Yes"
                }

                if p.annotation != inspect.Parameter.empty:
                    arg["type"] = portable_type_name(p.annotation)

                if p.default != inspect.Parameter.empty:
                    arg["required"] = "No"
                    if isinstance(p.default, str):
                        arg["default"] = '"{}"'.format(p.default)
                    else:
                        arg["default"] = json.dumps(p.default)
                args.append(arg)

            return_type = "None"
            if sig.return_annotation != inspect.Signature.empty:
                return_type = portable_type_name(sig.return_annotation)
                if return_type == "object":
                    return_type = repr(sig.return_annotation).replace(
                        "<class '", "").replace("'>", "").replace(
                            "typing.", "")


            can_be_called_without_args = args and not any(
                a["required"] == "Yes" for a in args)

            as_json = {
                "name": func_name.replace('_', '-'),
                "type": activity_type,
                "provider": {
                    "type": "python",
                    "module": mod_name,
                    "func": func_name
                }
            }
            if not can_be_called_without_args:
                if not args:
                    continue

                as_json["provider"]["arguments"] = {}
                for arg in args:
                    if arg["required"] == "No":
                        continue

                    arg_type = get_activity_default_value(arg["type"])
                    as_json["provider"]["arguments"][arg["name"]] = arg_type

            activities.append({
                "type": activity_type,
                "module": mod_name,
                "name": func_name,
                "doc": inspect.getdoc(func),
                "return": return_type,
                "signature": FormatCode("def {}{}:pass".format(
                    func_name, str(sig)))[0],
                "arguments": args,
                "as_json": json.dumps(as_json, indent=2),
                "as_yaml": yaml.dump(as_json, default_flow_style=False)
            })

        meta["activities"][target] = sorted(
            activities, key=itemgetter("name"))

    return meta