-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Refactor pyreverse Association Logic #10397
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the addition! π
I only left two remarks for cases where at least from the comment it seems like the relationship is processed by the wrong handler. Am I missing something?
It would be great if you can add tests for all possible output formats as all printers where changed. You can specify multiple output formats for a single functional test in the [testoptions]
.
Thanks for the review. I agree that the logic is not complete and it needs some more work and I need to figure out all the possible edge cases. Also I think some of the other tests have changed , and I need to rebase aswell. I think this will take some time, but lets see how it goes :) |
This comment has been minimized.
This comment has been minimized.
@Julfried please ping me once the PR is ready to be reviewed again. No hurry though, just want to point this out as I am not actively monitoring the open PRs and instead rely more on the email notifications. π |
This comment has been minimized.
This comment has been minimized.
Codecov Reportβ
All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #10397 +/- ##
==========================================
- Coverage 95.86% 95.85% -0.01%
==========================================
Files 176 177 +1
Lines 19155 19286 +131
==========================================
+ Hits 18363 18487 +124
- Misses 792 799 +7
π New features to boost your workflow:
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
@DudeNr33 Finally ready for review again. All functional tests are passing and the association logic is working correctly now. Interestingly, I figured while playing around that this PR also fixes #10333 (duplicate arrows issue) as a side effect. The root cause was the same - improper relationship classification led to the same attribute being processed multiple times across different relationship types. Our priority-based processing with duplicate prevention solves this at the source. This example from #10333: class A:
def __init__(self) -> None:
self.var = 2
class B:
def __init__(self) -> None:
self.a_obj = A()
def func(self):
self.a_obj = A()
self.a_obj = A() Now correctly produces single composition relationship instead of duplicates: classDiagram
class A {
var : int
}
class B {
a_obj
func()
}
A --* B : a_obj Should I add the functional test cases from #10333 to this PR, or handle them in a follow-up? The PR is getting quite large, but its up to you. The core association logic is solid and ready for review either way. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, that looks pretty good !
I think it's better to add functional test cases for the other issue here as you fixed it here. Usually we do another MR because we don't realise an issue is fixed until later. |
This comment has been minimized.
This comment has been minimized.
I updated the functional tests, so now this also Closes #9267 The example from #8046 currently produces this output: @startuml classes_toy_code
set namespaceSeparator none
class "ExampleClass" as parser.toy_code.ExampleClass {
example1 : Optional[int]
example2 : Optional[int]
}
@enduml However I think this is not the output the was discussed in the issue, since the class level attributes are still not handled correctly. Let me know what you think :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, although I'll let @DudeNr33 review the fine details. Great work clearly a lot of care went into this. Could you try to cover the missing lines maybe ?
Thanks for the review, I appreciate the kind words :) I remember the patch coverage initially dropped because I updated a base class, and only two lines were uncovered at that point. Now I see more lines are reported as missing β could this be because my branch is not up to date with main? Would it make sense to try a rebase to see if that clears it up? |
Yes, good idea ! |
β¦ass level attributes separate
β¦s composition instead of association)
β¦ fixes last failing test
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
This comment has been minimized.
This comment has been minimized.
Not sure why the workflow hangs? |
Sometime codecov is capricious like that. (Probably nothing to do with the PR itself) |
The same thing is happening for other PRs aswell, so it is definitly not related to the changes. Not sure what is happening here |
Glad I am not the only one that is seeing this. |
Any timeline from the admins to accept this pull request? |
I'd rather have a review from Andreas before merging and he might be in the wilderness without network vacationning atm. It's going to be in pylint 4.0 with high certainty (released around python 3.14 release). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for all the work that went into this, and sorry for the late review.
This looks very polished now. I only have one minor remark for the arrow direction of Associations. The rest looks good to me!
tests/pyreverse/functional/class_diagrams/relationships/fields.mmd
Outdated
Show resolved
Hide resolved
I assume you refer to the example in the initial issue description, i.e.: from typing import Optional
class ExampleClass():
example1 : Optional[int] = None
example2 : Optional[int] = None
def __init__(self):
self.example1 = 1
self.example2 = 2 In my opinion the current behavior is fine. Finding the right balance between
is not easy. If we want to properly differentiate between static (i.e. class) attributes and non-static (i.e. instance) attributes, we should consequently also differentiate between instance, class ( |
Co-authored-by: Andreas Finkler <[email protected]>
This comment has been minimized.
This comment has been minimized.
I reversed the arrows as requested, so the association direction should now be correct. I agree that handling all the nuances of class vs instance attributes would add significant complexity for uncertain benefit. Generating perfectly valid UML diagrams out of code is quite hard. Lets keep the issue open for the future :) |
π€ According to the primer, this change has no effect on the checked open source code. π€π This comment was generated for commit 90b243f |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the patience and persistence!
Type of Changes
Description
Closes #9045
Closes #9267
Summary
Fixed incorrect UML semantics in pyreverse for aggregation vs composition relationships. The previous implementation had no explicit
CompositionsHandler
class and did not differentiate between Aggregation and Composition properly, treating most relationships as aggregation by default.Problem
Pyreverse previously lacked proper UML relationship semantics. So I would proposes the following distinction for Python class relationships:
fields.py
fields.mmd
Changes Made
1. Added CompositionsHandler
Created dedicated handler following chain of responsibility pattern:
CompositionsHandler β AggregationsHandler β AssociationsHandler
2. Updated Printers
EdgeType.COMPOSITION
enum value3. Prevented Duplicate Relationships
Modified extract_relationships() to process relationships by priority and avoid duplicates.
Currently I only made the modifications needed to implement the new Associations Logic. If you like the proposed distinction I would work on making the tests pass :)