pyreverse is a great tool to generate UML diagram from Python codes. However, I found it cannot identify all the classes that has been used within a function. I take the following example to illustrate my point:
class ClassA(object):
def __init__(self):
pass
class ClassB(object):
def __init__(self):
pass
class ClassC(object):
def __init__(self):
self.object_b = ClassB()
def perform():
object_a = ClassA()
If we use pyreverse to generate class diagram, it is clear that we can see ClassB
is a component within ClassC
. However, it cannot generate the relationship with ClassA
, which is used in its function perform
. Is there any way for pyreverse to retrieve the relationship between ClassC
and ClassA
?
The reason is the scope of object_a
: it is a local variable of the function and not an instance variable. The relationship of C with A is therefore not structural. Hence, it is not an UML association (nor aggregation, nor composition).
At best, we could say there is a usage dependency from C to A. But this usage is specific to the implementation and not necessarily meant by design.
I’m not a Python expert, but if pyreverse is able to spot the right relation with object_b
, and if you’d make object_a
an instance variable with self.object_a
in the assignment, you can hope to get the result that you expected.
Edit: Experimental verification
If the class C is corrected as explained:
class ClassC(object):
def __init__(self):
self.object_b = ClassB()
def perform(self):
self.object_a = ClassA()
pyreverse generates indeed the right result as expected:
For a human reader, it's easy to miss a property. This is why pylint issues a warning on this code:
W0201: Attribute 'object_a' defined outside __init__ (attribute-defined-outside-init)
Note also that if you define a (static) class variable instead of an instance variable, pyreverse does not show it with an underlined name. The reason is probably, because it's not uncommon to hide a class variable with an instance variable of the same name.