使用复杂类型提示(Union,List,...)生成Pyreverse UML

5
我正在尝试为使用联合和列表类型提示的类生成UML图。一个例子如下:
from dataclasses import dataclass
from typing import Union   

@dataclass
class ClassA:
    name: str    

@dataclass
class ClassB:
    an_attribute: int    

@dataclass
class ClassC:
    my_class: Union[ClassA, ClassB]

在运行 pyreverse -ASmn stackoverflow_example.py -o png 命令时,我得到了一个 UML 图,该图未显示 classA 和 classB 的用法:

UML class diagram with three unconnected classes A,B and C

如果我将 ClassC 中的代码替换为:
@dataclass
class ClassC:
    my_class: ClassA

我得到了一个更接近我的目标的UML描述: UML类图,有3个类A、B和C,其中C由A组成 但是当我将类型为ClassB的东西分配给my_class时,这意味着我会收到一个警告提示,这正是它应该做的。 我对Union的理解是我会得到像这样的东西: 手动编辑的UML类图,有3个类A、B和C,C由A和B组成 示例中展示的是Union,但List和其他类似。 是否有一种方法可以做到这一点,还是这是一种不应该做的设计?

除了获得粗略的概述(在许多情况下可能有所帮助),我不会对任何此类工具放心。它们可能只是检查头文件而没有深入代码的内部(即声明)。顺便说一句,“越接近目标”的使用一个连接器的标签,并不反映代码的实际情况。 - qwerty_so
1个回答

6

在 UML 中应该如何表示?

根据指定类型提示的 PEP 484

由 Union[T1, T2, ...] 因式分解的类型是所有类型 T1、T2 等的超类型,因此一个属于这些类型之一的值可用于由 Union[T1, T2, ...] 注释的参数。

但在 UML 中,这将需要一个中间类型,因为只能有一个 my_class 成员:

enter image description here

如何在pyreverse中获取它?

查看pyreverse的不同选项,我们没有太多可以做的:

  • 您可以添加选项-b来包括内置类型。在这种情况下,您会看到所有类都继承自object,并且您会看到intstr包括该类型的成员组合。但是,Union仍然保持不变,并且没有显示任何类似于PEP 484建议的内容。这表明pyreverse不支持此功能。

  • 对于Union,Pyreverse显示的行为与添加不存在的类型(例如xxxx或甚至是无意义的xxx [1,2,yyy])完全相同:它指示源文件中的字符串,但不绘制相应的对象。这加强了缺乏支持的印象。

  • 最后一次尝试中,我在pyreverse中将typing.py软件包的示例文件一起处理。它很好地识别了包之间的依赖关系。但联合方面仍然没有变化。

  • 使用替代语法ClassA | ClassB会导致稍微不同的图表,因为类型信息完全被删除,但也没有显示组合。

我只能得出这个工具不支持联合类型的图形渲染的结论。
联合是一种实用的特性,但不太面向对象:
- UML没有直接支持它,您需要按照上面解释的方式处理它。 - 联合将可能不相关的类型组合在一起,这并不便于多态编程。
幸运的是,有一个简单的替代方法:让A和B成为一个共同的空类的子类,比如AB,然后将my_class作为AB。 Pyreverse然后生成预期的结果:

enter image description here


4
我可以确认,pyreverse 目前不支持此功能。从类型注释(如 Union 或 Optional)创建额外的中间图形节点不在此工具的范围内。 - dudenr33
@dudenr33非常感谢您提供的这个非常有用的确认。我可以问一下您是否是pylint贡献者团队的一员,或者您有其他来源吗? - Christophe
1
不仅是团队的一部分,而且在过去10年中对pyreverse进行的修改中负责超过60%(特别是plantuml实现)https://github.com/PyCQA/pylint/pulls?q=is%3Apr+author%3ADudeNr33+is%3Aclosed+label%3Atopic-pyreverse ;) - Pierre.Sassoulas
谢谢Christophe,我不知道这会违反UML。 有趣的是,对我来说,工具的目标似乎不受支持,因为没有箭头会令人困惑,而两者都清楚地突出了开发人员的意图。@dudenr33,您是否知道是否有可能在没有中间类型的情况下获得这些箭头,或者pyreverse是否以严格的UML为目标,因此这将与其哲学相悖? - Drooppi
2
@Drooppi,据我所知,目前没有办法仅通过类型提示显示两个组合箭头。这是因为,正如您已经注意到的那样,复杂的类型提示尚未得到很好的支持。pyreverse 的目标不是严格的 UML,只要图表的意图清晰即可。对于多重关联,实际上目前有一个开放的拉取请求:https://github.com/PyCQA/pylint/pull/6434。我已在 GitHub 上提出了一个功能请求,但我不能保证何时会实现:https://github.com/PyCQA/pylint/issues/6737。 - dudenr33
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接