【问题标题】:Is there any tool to create dependency graphs for GitHub private repositories mainly written in Python -only showing the private dependencies?是否有任何工具可以为主要用 Python 编写的 GitHub 私有存储库创建依赖关系图 - 仅显示私有依赖关系?
【发布时间】:2022-02-08 22:55:17
【问题描述】:

我在一家拥有几个私有存储库的公司工作 - 所有这些都主要用 Python 编写。
每个 repo 在其根目录下都有一个 requirements.txt 文件。

我们有兴趣列出每个存储库的依赖项和依赖项,而不是公共依赖项,而只是我们的私有依赖项和依赖项。

例如,假设 our_private_package1requirements.txt 文件如下所示:

public_package1
public_package2
public_package3
our_private_package2
our_private_package3

还假设有另一个包our_private_package4 具有以下requirements.txt 文件:

public_package2
public_package4
our_private_package1

所以我们想构建一个依赖关系图,我们可以在其中看到 our_private_package1 的以下内容:
依赖:

  • our_private_package2
  • our_private_package3

家属:

  • our_private_package4

理想情况下,我们希望用图表来可视化依赖关系。

2 个注释:

  • GitHub's solution 不适合这里有两个原因。首先,它 仅显示公共依赖项。也不能确定 私有存储库的依赖项(依赖项是否是公共的 或私人)。
  • 依赖项不应是可传递的。在上面的例子中,our_private_package2 不应该被列为 our_private_package4 的依赖项(尽管我们 应该在视觉表示中看到一条从 our_private_package2our_private_package4,具有从 our_private_package2our_private_package1 的定向分支和 从our_private_package1our_private_package4 的另一个分支)。

如果没有针对此类问题的可用工具,我至少想要一些指导如何使用一些 Python 代码来解决(几乎可以肯定它是可行的)。

【问题讨论】:

  • 为什么不直接使用Github's solution
  • 它只显示公共依赖。它也不能确定私有存储库的依赖项(依赖项是公共的还是私有的)。
  • 依赖可以/应该是传递的吗?我的意思是,如果 our_private_package5 依赖于 our_private_package4,是否应该将其列为依赖于 our_private_package1 ?我最近遇到了类似的问题,并且开发了一些自定义的东西(仅使用 Python 的 dicts、lists 和 sets,导出到 json 和 graphviz)。
  • 我更喜欢依赖不是传递的(尽管如果它们是传递的,它仍然提供有用的信息)。我希望我已经澄清了我在编辑后的问题中寻找的内容。在@0x263A 的问题之后,我还添加了我在第一条评论中所做的澄清。

标签: python github dependencies


【解决方案1】:

正如之前在 cmets 中提到的,我也有类似的需求。我使用与此类似的方法解决了它:

from collections import defaultdict
from typing import List, Tuple, Dict


def main():
    requirements_file_content_per_package = {
        "our_private_package1": """\
public_package1
public_package2
public_package3
our_private_package2
our_private_package3
        """,

        "our_private_package2": """\
public_package2
public_package4
our_private_package1
        """
    }

    private_packages_names = ["our_private_package1",
                              "our_private_package2",
                              "our_private_package3",
                              "our_private_package4"]

    # process descending dependency
    private_packages_dependencies: Dict[str, Tuple[List[str], List[str]]] = {}
    for private_package_name in private_packages_names:
        requirements_file_content = requirements_file_content_per_package.get(private_package_name, "")
        private_packages_dependencies[private_package_name] = classify_dependencies(requirements_file_content, private_packages_names)

    # display
    for private_package_name, (package_private_dependencies_names, _) in private_packages_dependencies.items():
        print(f"package {private_package_name!r} depends on private {package_private_dependencies_names!r}")

    # process ascending dependencies
    private_packages_dependents: Dict[str, List[str]] = defaultdict(list)
    for private_package_name, (package_private_dependencies_names, _) in private_packages_dependencies.items():
        for package_private_dependency_name in package_private_dependencies_names:
            private_packages_dependents[package_private_dependency_name].append(private_package_name)

    # display
    for private_package_name, package_private_dependents_names in private_packages_dependents.items():
        print(f"package {private_package_name!r} is depended on by private {package_private_dependents_names!r}")


def classify_dependencies(requirements_file_content: str, private_packages_names: List[str]) -> Tuple[List[str], List[str]]:
    private_dependencies: List[str] = []
    public_dependencies: List[str] = []
    for dependency_name in requirements_file_content.splitlines():
        is_private = dependency_name in private_packages_names
        if is_private:
            private_dependencies.append(dependency_name)
        else:
            public_dependencies.append(dependency_name)
    return private_dependencies, public_dependencies


main()

这有点粗糙,我使用的是非常基本的 Python(字符串、列表和集合),但可以使用有向彩色图代替。另外,名字很长,因为我想要描述性,但我认为使用简洁的定义词汇会更好。

至于可视化:

    import graphviz  # installed with pip

    dot = graphviz.Digraph()
    # at first, create all the nodes
    for private_package_name in private_packages_names:
        dot.node(private_package_name)
    # then create the edges
    for private_package_name, package_private_dependents_names in private_packages_dependents.items():
        for package_private_dependent_name in package_private_dependents_names:
            dot.edge(package_private_dependent_name, private_package_name)
    dot.render("deps.gv", format="png")

出品deps.gv.png :

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-31
    • 1970-01-01
    • 2017-01-29
    • 1970-01-01
    • 1970-01-01
    • 2016-03-18
    • 2015-04-28
    相关资源
    最近更新 更多