pydmt.helpers.python — pydmt Documentation

# Source code for pydmt.helpers.python

    """
    python.py
    """

    import os
    import os.path
    import importlib
    import glob
    import pprint
    from collections.abc import Callable

    def make_console_script(package_name: str, main: Callable):
        """
        return a string suitable to be used as the section "console_scripts"
        of the "entry_points" parameters of setup.py.

        example: "pycmdtools=pycmdtools.endpoints.main:main"
        :param package_name:
        :param main:
        :return:
        """
        return f"{package_name}={getattr(main, '__module__')}:{main.__name__, }"

    def array_indented(level: int, array: list[str], quote_char="\"", comma_after=False) -> str:
        """
        return an array indented according to indent level
        :param level:
        :param array:
        :param quote_char:
        :param comma_after:
        :return:
        """
        out = "[\n"
        for x in array:
            out += (((level + 1) * 4) * " ") + f"{quote_char}{x}{quote_char}" + ",\n"
        out += ((level * 4) * " ") + "]"
        if comma_after:
            out += ","
        return out

    def dict_indented(level: int, dictionary: dict[str, list[int]], quote_char="\"", comma_after=False) -> str:
        """
        return an dict indented according to indent level
        :param level:
        :param dictionary:
        :param quote_char:
        :param comma_after:
        :return:
        """
        out = "{\n"
        for k, v in dictionary.items():
            spaces = ((level + 1) * 4) * " "
            out += f"{spaces}{quote_char}{k}{quote_char}: {v},\n"
        spaces = (level * 4) * " "
        out += f"{spaces}}}"
        if comma_after:
            out += ","
        return out

    def find_packages(path: str) -> list[str]:
        """
        A better version of find_packages than what setuptools offers
        This function needs to be deterministic.
        :param path:
        :return:
        """
        ret = []
        for root, _dir, files in os.walk(path):
            if "__init__.py" in files:
                ret.append(root.replace("/", "."))
        return sorted(ret)

    def get_list_unquoted(a_list: list[str]) -> str:
        """
        The exact format of this output is to be used in python code from templates,
        that is why the left bracket ([) does not have space following it and the
        same for the right bracker (]).
        """
        s = "["
        s += ", ".join(a_list)
        s += "]"
        return s

    def get_list_quoted(a_list: list[str]) -> str:
        """
        The exact format of this output is to be used in python code from templates,
        that is why the left bracket ([) does not have space following it and the
        same for the right bracker (]).
        """
        quoted = map(lambda x: f"\"{x}\"", a_list)
        s = "["
        s += ", ".join(quoted)
        s += "]"
        return s

    def get_package_name():
        mod = importlib.import_module("config.python")
        if hasattr(mod, "package_name"):
            return getattr(mod, "package_name")
        return os.path.basename(os.getcwd())

    def get_attr(attr: str):
        mod = importlib.import_module("config.python")
        if hasattr(mod, attr):
            return getattr(mod, attr)
        # TODO: need a better exception type (make my own)
        raise ValueError(f"cannot find {attr}")

    def get_license_type():
        return get_attr("license_type")

    def get_platforms():
        return get_attr("platforms")

    def get_classifiers():
        return get_attr("classifiers")

    def hlp_source_under(folder):
        """
        this function finds all the python packages under a folder and
        write the "packages" and "package_dir" entries for a python setup.py
        script
        """
        # walk the folder and find the __init__.py entries for packages.
        packages = []
        package_dir = {}
        for root, _dirs, files in os.walk(folder):
            for file in files:
                if file != "__init__.py":
                    continue
                full = os.path.dirname(os.path.join(root, file))
                relative = os.path.relpath(full, folder)
                packages.append(relative)
                package_dir[relative] = full
        # we use pprint because we want the order to always remain the same
        return f"packages={sorted(packages)},\npackage_dir={pprint.pformat(package_dir)}"

    def hlp_files_under(dest_folder, pat):
        return f"(\"{dest_folder}\", {[x for x in glob.glob(pat) if os.path.isfile(x)]})"

    def make_hlp_project_keywords(d):
        def hlp_project_keywords():
            return f"{d.project_keywords.split()}"
        return hlp_project_keywords

    def make_hlp_project_platforms(d):
        def hlp_project_platforms():
            return f"{d.project_platforms.split()}"

        return hlp_project_platforms

    def make_hlp_project_classifiers(d):
        def hlp_project_classifiers():
            cls_list = d.project_classifiers.split("\n")
            cls_list = [x.strip()[1:-1] for x in cls_list]
            return f"{cls_list}"

        return hlp_project_classifiers

    def make_hlp_wrap(level):
        def hlp_wrap(t):
            return t.replace("\n", "\n" + "\t" * level)
        return hlp_wrap